找到干草堆中所有针的位置

时间:2012-05-14 15:37:33

标签: php strpos

我试图在大海捞针中找到所有针头的位置:

$haystack = 'one twoo two one postpone twool';
$needles = array('one', 'two', 'three');
foreach ($needles as $needle) { 
  if (stristr($haystack, $needle)) { // list position of all needles
    $pos[strpos($haystack, $needle)] = $needle;
  }
}
print_r($pos);

$pos的值在这里:

Array ( [0] => one [4] => two ) 

然而,预期是:

Array ( [0] => one [9] => two [13] => one) 

所以有两件事情出错:

  • twoo被标记为two
  • 的出现
  • 循环显然与one
  • 的第二次出现不匹配

我做错了什么?

5 个答案:

答案 0 :(得分:2)

如果您想要一种简单的方法,可以使用preg_match

foreach ($needles as $needle) {
    if( preg_match_all( '/\b' . $needle . '\b/', $haystack, $matches, PREG_OFFSET_CAPTURE ) ) {
        foreach( $matches[0] as $match )
            $pos[$match[1]] = $needle;
    }
}

答案 1 :(得分:1)

根据Rawkode的建议:

function strpos_recursive($haystack, $needle, $offset = 0, &$results = array()) {                
    $offset = strpos($haystack, $needle, $offset);
    if($offset === false) {
        return $results;            
    } else {
        if(substr ($haystack, $offset + strlen ($needle), 1) == ' ' || ( $offset + strlen ($needle) ) == strlen ($haystack)) {  
            if(substr ($haystack, $offset - 1, 1) == ' ' || $offset == 0) {
                $results[$offset] = $needle;
            }
        }
        return strpos_recursive($haystack, $needle, ($offset + 1), $results);
    }
}

$haystack = 'one twoo two one postpone twool one three';
$needles = array('one', 'two', 'three');
$pos = array ();

foreach ($needles as $needle) { 
    if (stristr($haystack, $needle)) {
        $pos += strpos_recursive($haystack, $needle);
    }
}
ksort($pos);
print_r($pos);

我还添加了一个检查,以确保下一个字符是空格,或者它已经是干草堆的末尾,所以它不会匹配twoo之类的内容。

答案 2 :(得分:1)

你应该使用正则表达式。试试这个:

$haystack = 'one twoo two one postpone twool';
$needles = array('one', 'two', 'three');

foreach($needles as $needle) 
{
    $regex = "/\b$needle\b/";

    if (preg_match_all($regex, $haystack, $matches, PREG_OFFSET_CAPTURE))
    {
        if (is_array($matches[0]))
        {
            foreach($matches[0] as $match)
            {
                $pos[$match[1]] = $match[0];
            }
        }

    }
}

print_r($pos);

输出是:

Array
(
    [0] => one
    [13] => one
    [9] => two
)

答案 3 :(得分:0)

您需要按顺序添加上次找到的位置的偏移量以查找将来的事件。

有人已经在文档评论中提供了这样的解决方案 http://www.php.net/manual/en/function.strpos.php#107678

答案 4 :(得分:0)

第一点: 使用stristr可以接受每个子字符串作为解决方案,因此我建议使用正则表达式(请参阅preg_match_all)。

第二点: 对于数组的每个元素,从haystack的开头搜索字符串,只进行第一次匹配。 再次使用preg_match_all!