Как очистить массив массивов с помощью полудублирующих значений на основе ключей в PHP?

Предположим, мы делаем какую-то очистку, и в итоге мы можем получить как дублированные, так и полудублированные результаты.

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

$inputArr = [
[
'title' => 'Test0',
'desc'  => 'Short Desc',
],
[
'title' => 'Test5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test0',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test0.5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test1',
'desc'  => 'Short Desc',
],
[
'title' => 'Test1',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test1.5',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test3',
'desc'  => 'Short Desc',
],
[
'title' => 'Test2',
'desc'  => 'Short Desc',
],
[
'title' => 'Test3.75',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test3.25',
'desc'  => 'Short Desc',
],
[
'title' => 'Test2',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test3',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test5',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test3.5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test4',
'desc'  => 'Short Desc',
],
[
'title' => 'Test5',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test4.5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test4',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test5',
'desc'  => 'Much Longer Than Short Desc',
],
];

Полученный массив должен содержать только массивы с ОДНЫМ экземпляром title значение где desc самое длинное строковое значение при удалении всех, кроме одного, где desc имеет значение длины строки, равное другим.

например конечный результат должен выглядеть следующим образом:

$resultArr = [
[
'title' => 'Test0',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test0.5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test1',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test1.5',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test2',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test3',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test3.25',
'desc'  => 'Short Desc',
],
[
'title' => 'Test3.5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test3.75',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test4',
'desc'  => 'Much Longer Than Short Desc',
],
[
'title' => 'Test4.5',
'desc'  => 'Short Desc',
],
[
'title' => 'Test5',
'desc'  => 'Much Longer Than Short Desc',
],
];

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

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

1

Решение

Вы можете сделать это так:

foreach($inputArr as $item) {

if ( isset($result[$item['title']]) && strlen($result[$item['title']]['desc']) > strlen($item['desc']) )
continue;

$result[$item['title']] = $item;
}

$result = array_values($result);

print_r($result);

демонстрация

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

Вы также можете использовать array_reduce:

$result = array_reduce($inputArr, function ($c, $i) {
if ( !isset($c[$i['title']]) || strlen($c[$i['title']]['desc']) < strlen($i['desc']) )
$c[$i['title']] = $i;

return $c;
});


$result = array_values($result);

print_r($result);
2

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

Других решений пока нет …