PHP найти n-грамм в массиве

У меня есть массив PHP:

$excerpts = array(
'I love cheap red apples',
'Cheap red apples are what I love',
'Do you sell cheap red apples?',
'I want red apples',
'Give me my red apples',
'OK now where are my apples?'
);

Я хотел бы найти все n-граммы в этих строках, чтобы получить такой результат:

  • дешевые красные яблоки: 3
  • красные яблоки: 5
  • яблоки: 6

Я попытался взорвать массив и затем проанализировать его, но это глупо, потому что новые n-граммы могут быть найдены из-за конкатенации строк, которым нечего видеть между собой.

Как бы вы поступили?

-2

Решение

Я хочу найти группу слов, не зная их, хотя
с вашей функцией мне нужно предоставить их, прежде чем что-либо

Попробуй это:

mb_internal_encoding('UTF-8');

$joinedExcerpts = implode(".\n", $excerpts);
$sentences = preg_split('/[^\s|\pL]/umi', $joinedExcerpts, -1, PREG_SPLIT_NO_EMPTY);

$wordsSequencesCount = array();
foreach($sentences as $sentence) {
$words = array_map('mb_strtolower',
preg_split('/[^\pL+]/umi', $sentence, -1, PREG_SPLIT_NO_EMPTY));
foreach($words as $index => $word) {
$wordsSequence = '';
foreach(array_slice($words, $index) as $nextWord) {
$wordsSequence .= $wordsSequence ? (' ' . $nextWord) : $nextWord;
if( !isset($wordsSequencesCount[$wordsSequence]) ) {
$wordsSequencesCount[$wordsSequence] = 0;
}
++$wordsSequencesCount[$wordsSequence];
}
}
}

$ngramsCount = array_filter($wordsSequencesCount,
function($count) { return $count > 1; });

Я предполагаю, что вы хотите только повторную группу слов.
Выход из var_dump($ngramsCount); является:

array (size=11)
'i' => int 3
'i love' => int 2
'love' => int 2
'cheap' => int 3
'cheap red' => int 3
'cheap red apples' => int 3
'red' => int 5
'red apples' => int 5
'apples' => int 6
'are' => int 2
'my' => int 2

Код можно оптимизировать, чтобы, например, использовать меньше памяти.

2

Другие решения

Код предоставлен Педро Амарал Коуту выше очень хорошо.
Поскольку я использую его для французского, я изменил регулярное выражение следующим образом:

$sentences = preg_split('/[^\s|\pL-\'’]/umi', $joinedExcerpts, -1, PREG_SPLIT_NO_EMPTY);

Таким образом, мы можем проанализировать слова, содержащие дефисы и апострофы («est-ce que», «j’ai» и т. Д.)

1

Попробуйте это (используя implode, так как это вы упомянули как попытку):

$ngrams = array(
'cheap red apples',
'red apples',
'apples',
);

$joinedExcerpts = implode("\n", $excerpts);
$nGramsCount = array_fill_keys($ngrams, 0);
var_dump($ngrams, $joinedExcerpts);
foreach($ngrams as $ngram) {
$regex = '/(?:^|[^\pL])(' . preg_quote($ngram, '/') . ')(?:$|[^\pL])/umi';
$nGramsCount[$ngram] = preg_match_all($regex, $joinedExcerpts);
}
0

Предполагая, что вы просто хотите посчитать количество вхождений строки:

$cheapRedAppleCount = 0;
$redAppleCount = 0;
$appleCount = 0;
for($i = 0; $i < count($excerpts); $i++)
{
$cheapRedAppleCount += preg_match_all('cheap red apples', $excerpts[$i]);
$redAppleCount += preg_match_all('red apples', $excerpts[$i]);
$appleCount += preg_match_all('apples', $excerpts[$i]);
}

preg_match_all возвращает количество совпадений в данной строке, так что вы можете просто добавить количество совпадений на счетчик.

preg_match_all для дополнительной информации.

Извиняюсь, если я неправильно понял.

-1
По вопросам рекламы [email protected]