Как искать часть строки в массиве? - PullRequest
2 голосов
/ 19 июля 2011

Я хочу узнать, является ли полная строка или ее часть частью массива. Как это может быть достигнуто в PHP?

Кроме того, как я могу использовать в нем метафон ?

Пример:

array1={'India','USA','China'};
array2={'India is in east','United States of America is USA','Made in China'}

Если я ищу array1 в array2, то:

«Индия» должна соответствовать «Индия на востоке» и аналогично для США и Китая.

Ответы [ 3 ]

4 голосов
/ 19 июля 2011
$array1 = array('India','USA','China');
$array2 = array('India is in east','United States of America is USA','Made in China');
$found = array();

foreach ($array1 as $key => $value) {
    // Thanks to @Andrea for this suggestion:
    $found[$value] = preg_grep("/$value/", $array2);
    // Alternative:
    //$found = $found + preg_grep("/$value/", $array2);
}

print_r($found);

Результат:

Array
(
    [0] => India is in east
    [1] => United States of America is USA
    [2] => Made in China
)

Использовать Метафон сложнее. Вам нужно будет определить, из чего состоит матч. Один из способов сделать это - использовать расстояние Левенштейна между результатами метафона для двух сравниваемых значений.

Обновление: См. @ Андреа решение для более разумного сравнения метафонов для каждого слова.

Вот пример:

$meta1 = array_map(
    create_function( '$v', 'return array(metaphone($v) => $v);' ),
    $array1
);

$meta2 = array_map(
    create_function( '$v', 'return array(metaphone($v) => $v);' ),
    $array2
);

$threshold = 3;

foreach ($meta2 as $key2 => $value2) {

    $k2 = key($value2);
    $v2 = $value2[$k2];

    foreach ($meta1 as $key1 => $value1) {

        $k1  = key($value1);
        $v1  = $value1[$k1];
        $lev = levenshtein($k2, $k1);

        if( strpos($v2, $v1) !== false || levenshtein($k2, $k1) <= $threshold ) {
            array_push( $found, $v2 );
        }
    }
}

... но для этого нужна работа. Это производит дубликаты, если порог слишком высок. Вы можете предпочесть провести матч в два прохода. Один для поиска простых совпадений, как в моем первом примере кода, а затем другой для сопоставления с метафоном, если первый не возвращает совпадений.

1 голос
/ 19 июля 2011

Корпус метафона может также следовать той же структуре, предложенной Майком для строгого случая.

Я не думаю, что необходима дополнительная функция сходства, потому что цель метафона должна состоять в том, чтобы дать нам ключ, который является общим для слов, которые звучат одинаково.

$array1 = array('India','USA','China');
$array2 = array(
    'Indiuh is in east',
    'United States of America is USA',
    'Gandhi was born in India',
    'Made in China'
);
$found = array();
foreach ($array1 as $key => $value) {
    $found[$value] = preg_grep('/\b'.$value.'\b/i', $array2);
}

var_export($found);

echo "\n\n";

function meta( $sentence )
{
    return implode(' ', array_map('metaphone', explode(' ', $sentence)));
}

$array2meta = array_map('meta', $array2);
foreach ($array1 as $key => $value) {
    $valuemeta = meta($value);
    $foundmeta[$value] = preg_grep('/\b'.$valuemeta.'\b/', $array2meta);
    $foundmeta[$value] = array_intersect_key($array2, $foundmeta[$value]);
}

var_export($foundmeta);

Вышеприведенный код распечатывается:

array (
  'India' => 
  array (
    2 => 'Gandhi was born in India',
  ),
  'USA' => 
  array (
    1 => 'United States of America is USA',
  ),
  'China' => 
  array (
    3 => 'Made in China',
  ),
)

array (
  'India' => 
  array (
    0 => 'Indiuh is in east',
    2 => 'Gandhi was born in India',
  ),
  'USA' => 
  array (
    1 => 'United States of America is USA',
  ),
  'China' => 
  array (
    3 => 'Made in China',
  ),
)
0 голосов
/ 19 июля 2011
$a1 = array('India','USA','China');
$a2 = array('India is in east','United States of America is USA','Made in China');


foreach ( $a2 as $a )
{
  foreach( $a1 as $b  )
  {
    if ( strpos( $a, $b ) > -1 )
    {
      echo $a . " contains " . $b . "\n";
    }
  }
}
...