TransWikia.com

Проблема с выводом уникальных слов в тексте

Stack Overflow на русском Asked by Yurii on February 27, 2021

Всем доброго дня, пытаюсь реализовать функцию которая будет выводить из текста только те слова которые встречаются не больше одного раза. К примеру ( #[^a-z-]# ) – эта регулярка помогла мне вывести все слова и сколько раз встречаются они в тексте, я думал простым решением будет так же сделать другую регулярку что бы вывести только определенные слова а не все, но почему то не получается.

Это текст:

$text = ["Georgie follows his boat as it sails along Witcham Street, wishing Bill could be with him to see it go because Georgie is not as good as Bill at telling stories about what
    he sees. A current takes the boat into a storm drain, and Georgie peeks inside to look for it. 
    In the drain Georgie sees a pair of yellow eyes. Scared, he begins to back away, but a voice speaks to him. 
    Georgie looks back and sees a clown; the clown introduces himself as 'Mr. Bob Gray, also known as Pennywise the Dancing Clown.' 
    Georgie at first thought the drain smelled like his scary cellar at home, but now he can smell a carnival. 
    Pennywise has Georgie's boat in one hand and a balloon in the other; he offers Georgie both. 
    When Georgie reaches forward, Pennywise grabs Georgie's arm and rips it off.
    Georgie dies immediately. Dave Gardner, arriving 'only 45 seconds after the first scream,' finds Georgie's body. 
    The sheriff tells reporters Georgie must have got his arm stuck in a fast current in the storm drain. 
    Mrs. Denbrough is sedated in the local emergency room; Bill remains sick in bed, listening to his father weep in another room. 
    The paper boat continues through the sewers to the Penobscot River and out to sea as the rain clouds break overhead."];

Код:

function get_word_counts($text) {
    $counts = [];

    foreach ( $text as $phrase ) {
        $words = explode(' ', strtolower($phrase));
        foreach ( $words as $word ) {
            $word = preg_replace( "#s(w+s)1#siu", "$1", $word );
            $counts[ $word ] += 1;
        }

    }

    return $counts;
}

$counts = get_word_counts($text);
arsort($counts );

var_dump($counts);

One Answer

На что стоит обратить внимание в тексте:

  • текст разделяется не только пробелами, но и точками, запятыми, точкой с запятой и т.п.
  • есть слова в притяжательном падеже, которые имеют ', они в этом коде тоже разбиты, но чтобы этого не делать, можно удалить кавычку из регулярного выражения;
  • в результате разбиения слов в притяжательном падеже появилась буква 's'. Это не слово и для нее в коде можно сделать исключение, или же использовать это как одно слово. Как вам угодно.

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

Обратите внимание на ваш начальный код: $counts[ $word ] += 1;. Здесь нет проверки на существование элемента в массиве по данному ключу, и из-за этого идут предупреждения, но код рабочий.

Остальные комментарии в коде.

  function get_word_counts($text) {
    $counts = [];

    foreach ( $text as $phrase ) {
        // Вариант 1. Разбиваем строку по символам не образующим "слова". Словами в этом случае будут и числа. 
        // $words = preg_split('/W+/', strtolower($phrase));

        // Вариант 2. Разбиваем строку по символам не являющимися буквами. Цифр тут не будет.
        $words = preg_split('/[^[:alpha:]]+/', strtolower($phrase));
    
    foreach ( $words as $word ) {
        if (!isset($counts[$word])) {
            $counts[$word] = 0;
        }
        
        $counts[$word] += 1;
    }

    return $counts;
}

// Отфильтруем результат и получим слова, которые встречаются более одного раза
function get_words_that_more_one($text) {
    $counts = get_word_counts($text);

    return array_filter($counts, function($count) {
       return $count > 1; 
    });
}


$moreOne = get_words_that_more_one($text);

arsort($moreOne);

var_dump($moreOne);

Answered by Oleg Dmitrochenko on February 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP