Задача: Статистика слов в предложении
Glossary overview

Задача: Статистика слов в предложении

Фабула

Напиши функцию analyzeSentence($sentence), которая принимает строку — одно предложение на английском языке, и возвращает ассоциативный массив со следующей информацией:

  1. word_count — количество слов в предложении.
  2. unique_words — количество уникальных слов (без учёта регистра).
  3. longest_word — самое длинное слово в предложении.
  4. words — массив всех слов, приведённых к нижнему регистру, отсортированных по алфавиту.
// Ожидаемый результат:
Array
(
    [word_count] => 7
    [unique_words] => 5
    [longest_word] => great
    [words] => Array
        (
            [0] => and
            [1] => fun
            [2] => great
            [3] => is
            [4] => is
            [5] => php
            [6] => php
        )
)

Мое решение:

<?php

	$string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit lorem Lorem';
	
	function analyzeSentence($sentence) {
		
		$sentence = strtolower($sentence);
		$words = explode(" ", $sentence);
		$words_quantity = count($words);
		$unique_words = array_unique($words);
		
		// the longest word
		$longest = '';
		
		foreach ($unique_words as $word) {
			if (strlen($word) > strlen($longest)) {
				$longest = $word;
			}	
		}
		
		asort($unique_words);
		
		$result = [];
		$result[] = ["word_count" => $words_quantity];
		$result[] = ["unique_words" => count($unique_words)];
		$result[] = ["longest_word" => $longest];
		$result[] = ["words" => $unique_words];
			
		print_r($result);
		
	}
	
	analyzeSentence($string);

// Вывод

Array
(
    [0] => Array
        (
            [word_count] => 10
        )

    [1] => Array
        (
            [unique_words] => 8
        )

    [2] => Array
        (
            [longest_word] => consectetur
        )

    [3] => Array
        (
            [words] => Array
                (
                    [6] => adipiscing
                    [4] => amet,
                    [5] => consectetur
                    [2] => dolor
                    [7] => elit
                    [1] => ipsum
                    [0] => lorem
                    [3] => sit
                )

        )

)

А теперь давай немного улучшим твоё решение, чтобы оно:

  1. Убирало знаки препинания (например, запятые, точки и т.п.), чтобы amet, стало amet.
  2. Возвращало один ассоциативный массив, как в условии, а не массив массивов.
  3. Возвращало все слова, а не только уникальные — в words должны быть все слова, приведённые к нижнему регистру и отсортированные.

Вот как это можно доработать:

<?php

$string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit lorem Lorem';

function analyzeSentence($sentence) {
    // Удаляем знаки препинания и приводим к нижнему регистру
    $cleaned = strtolower(preg_replace("/[^\w\s]/u", "", $sentence));

    // Разбиваем строку на слова
    $words = explode(" ", $cleaned);
    $word_count = count($words);

    // Уникальные слова
    $unique_words = array_unique($words);
    $unique_count = count($unique_words);

    // Самое длинное слово
    $longest = '';
    foreach ($unique_words as $word) {
        if (strlen($word) > strlen($longest)) {
            $longest = $word;
        }
    }

    // Сортируем массив всех слов
    $sorted_words = $words;
    sort($sorted_words);

    // Результат
    return [
        "word_count" => $word_count,
        "unique_words" => $unique_count,
        "longest_word" => $longest,
        "words" => $sorted_words
    ];
}

print_r(analyzeSentence($string));

// Вывод
Array
(
    [word_count] => 10
    [unique_words] => 8
    [longest_word] => consectetur
    [words] => Array
        (
            [0] => adipiscing
            [1] => amet
            [2] => consectetur
            [3] => dolor
            [4] => elit
            [5] => ipsum
            [6] => lorem
            [7] => lorem
            [8] => lorem
            [9] => sit
        )
)

✅ Что можно еще улучшить:

1. Разбиение на подфункции (SRP – Single Responsibility Principle)

У тебя функция делает несколько вещей: очищает строку, разбивает, ищет длинное слово и т.д. Можно вынести эти действия в отдельные функции.

2. Использование array_reduce вместо foreach

Это современный, декларативный стиль. Повышает читаемость.

3. Типы параметров и возвращаемое значение (начиная с PHP 7.0+)

Добавляем string и array в сигнатуру функции. (Типизация)

declare(strict_types=1); — включает строгую типизацию в PHP-файле.

По умолчанию, PHP не строгий к типам. Это значит, что если ты напишешь:

function add(int $a, int $b): int {
    return $a + $b;
}

echo add("5", "10"); // РАБОТАЕТ, PHP преобразует строки в числа

Но если ты добавишь в начало файла:

declare(strict_types=1);

function add(int $a, int $b): int {
    return $a + $b;
}

echo add("5", "10"); // ❌ Ошибка: аргумент должен быть int, а не string

📌 Что важно помнить:

  • declare(strict_types=1); работает только в файле, где он объявлен, и только для скалярных типов (int, string, bool, float).
  • Он помогает писать более надёжный и предсказуемый код.
  • Без него PHP будет мягко приводить типы, что может скрывать ошибки.

4. Пример использования array_map / array_filter / array_reduce — современные подходы

Это не must, но они прокачивают мышление и делают код короче и выразительнее.

🔧 Отрефакторенный код:

<?php

declare(strict_types=1);

$string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit lorem Lorem';

function cleanSentence(string $sentence): string {
    return strtolower(preg_replace("/[^\w\s]/u", "", $sentence));
}

function getWords(string $sentence): array {
    return explode(" ", trim($sentence));
}

function getLongestWord(array $words): string {
    return array_reduce($words, function($longest, $word) {
        return strlen($word) > strlen($longest) ? $word : $longest;
    }, '');
}

function analyzeSentence(string $sentence): array {
    $cleaned = cleanSentence($sentence);
    $words = getWords($cleaned);
    $sorted_words = $words;
    sort($sorted_words);

    $unique_words = array_unique($words);

    return [
        'word_count' => count($words),
        'unique_words' => count($unique_words),
        'longest_word' => getLongestWord($unique_words),
        'words' => $sorted_words,
    ];
}

print_r(analyzeSentence($string));