创建准确的圣经搜索

时间:2012-10-30 14:04:56

标签: php

我正在创建一个圣经搜索。圣经搜索的问题在于人们经常进行不同类型的搜索,我需要相应地进行拆分。所以我认为最好的方法是删除所有空格,并在那里处理字符串。不同类型的搜索可能是:

Genesis 1:1 - 创世纪第1章,第1节

1 Kings 2:5 - 列王记下第2章,第5节

Job 3 - 工作第3章

Romans 8:1-7 - 罗马书第8章第1至7节

1 John 5:6-11 - 约翰福音第5章6 - 11节。

我不会对不同类型的搜索过于分阶段,但如果有人能找到更简单的方法来做到这一点或者知道这样做的好方法,那么请告诉我如何!

由于

5 个答案:

答案 0 :(得分:1)

这里最简单的方法是编写一个正则表达式来捕获文本,然后解析捕获以查看你得到的内容。首先,假设您有测试平台:

$tests = array( 
    'Genesis 1:1' => 'Genesis Chapter 1, Verse 1',
    '1 Kings 2:5' => '1 Kings Chapter 2, Verse 5',
    'Job 3' => 'Job Chapter 3',
    'Romans 8:1-7' => 'Romans Chapter 8, Verses 1 to 7',
    '1 John 5:6-11' => '1 John Chapter 5, Verses 6 to 11'
);

所以,你从左到右:

  1. 书名,可选择带有数字前缀
  2. 章节编号
  3. 一个经文编号,可选,后跟一个范围。
  4. 因此,我们可以编写一个正则表达式来匹配所有这些情况:

    ((?:\d+\s)?\w+)\s+(\d+)(?::(\d+(?:-\d+)?))?
    

    现在看看我们从正则表达式中得到什么:

    foreach( $tests as $test => $answer) {
        // Match the regex against the test case
        preg_match( $regex, $test, $match);
    
        // Ignore the first entry, the 2nd and 3rd entries hold the book and chapter
        list( , $book, $chapter) = array_map( 'trim', $match);
    
        $output = "$book Chapter $chapter";
    
        // If the fourth match exists, we have a verse entry
        if( isset( $match[3])) {
            // If there is no dash, it's a single verse
            if( strpos( $match[3], '-') === false) {
                $output .= ", Verse " . $match[3];
            } else {
                // Otherwise it's a range of verses
                list( $start, $end) = explode( '-', $match[3]);
                $output .= ", Verses $start to $end";
            }
        }
        // Here $output matches the value in $answer from our test cases
        echo $answer . "\n" . $output . "\n\n";
    }
    

    您可以在this demo中看到它。

答案 1 :(得分:0)

我想我明白你在这里问的是什么。您想要设计一个提取信息的算法(例如书名,章节,经文/诗句)。

这对我来说就像一个模式匹配的工作(例如正则表达式),因为你可以定义模式,为所有有意义的场景提取数据并从那里开始工作。

实际上可能存在相当多的变体 - 也许您还应该看看自然语言处理。名称上的模糊字符串匹配可以提供更好的结果(例如,人们拼错书籍名称)。

祝你好运

答案 2 :(得分:0)

尝试基于preg_match_all的内容,例如:

$ php -a
Interactive shell

php > $s = '1 kings 2:4 and 1 sam 4-5';
php > preg_match_all("/(\\d*|[^\\d ]*| *)/", $s, $parts);
php > print serialize($s);

答案 3 :(得分:0)

好吧,我对正则表达式不太确定,我还没有研究过它们,所以我坚持使用更多的程序方法。我已经做了以下(这仍然是我5年前编写的代码的一个巨大的改进,这是我的目标实现)这似乎完美无缺:

首先需要此功能:

    function varType($str) {
        if(is_numeric($str)) {return false;}    
        if(is_string($str)) {return true;}  
    }


    $bible = array("BookNumber" => "", "Book" => "", "Chapter" => "", "StartVerse" => "", "EndVerse" => "");    
  $pos = 1; // 1 - Book Number
        // 2 - Book 
        // 3 - Chapter 
        // 4 - ':' or 'v'
        // 5 - StartVerse
        // 6 - is a dash for spanning verses '-'
        // 7 - EndVerse
    $scan = ""; $compile = array();
    //Divide into character type groups.    
    for($x=0;$x<=(strlen($collapse)-1);$x++)
    {   if($x>=1) {if(varType($collapse[$x]) != varType($collapse[$x-1])) {array_push($compile,$scan);$scan = "";}}
        $scan .= $collapse[$x];
        if($x==strlen($collapse)-1) {array_push($compile,$scan);}
    }
    //If the first element is not a number, then it is not a numbered book (AKA 1 John, 2 Kings), So move the position forward.
    if(varType($compile[0])) {$pos=2;}
    foreach($compile as $val)
    {   if(!varType($val)) 
        {   switch($pos) 
            {   case 1: $bible['BookNumber'] = $val;    break;      
                case 3: $bible['Chapter'] = $val;   break; 
                case 5: $bible['StartVerse'] = $val;    break; 
                case 7: $bible['EndVerse'] = $val;  break; 
            }
        } else {switch($pos) 
            {   case 2: $bible['Book'] = $val;      break;      
                case 4:     //Colon or 'v'
                case 6: break;  //Dash for verse spanning. 
            }}
        $pos++;
    }

这将为您提供一个名为“Bible”的数组,该数组将包含在SQL数据库或您可能想要的其他任何内容上运行的所有必要数据。希望这有助于其他人。

答案 4 :(得分:0)

我知道这是疯狂的谈话,但为什么不只是有一个包含4个字段的表单,以便他们可以指定:

  1. 启动诗歌
  2. 结束诗歌[可选]