У меня есть идея из предыдущих сообщений, которые говорили о создании хэш-значения для каждого массива $ [$ i], а затем сравнить хеш для получения уникального массива, но я не знаю, что я могу сделать точно.
Мой массив образцов данных:
$arr[] = array(0,1,2,3); $arr[] = array(4,5,2,1); $arr[] = array(0,0,0,0); $arr[] = array(0,1,2,3);
Я ожидал возвращения:
$arr[] = array(0,1,2,3); $arr[] = array(4,5,2,1); $arr[] = array(0,0,0,0);
Может ли кто-нибудь отправить мне функцию для этой цели?
Большое спасибо!
Быстро и просто:
$arr = array_map('unserialize', array_unique(array_map('serialize', $arr)));
foreach($arr as $key => $value) { foreach($arr as $key2 => $value2) { if($value2 == $value && $key != $key2) { unset($arr[$key]); } } }
сforeach($arr as $key => $value) { foreach($arr as $key2 => $value2) { if($value2 == $value && $key != $key2) { unset($arr[$key]); } } }
Это не самый элегантный метод, но он делает именно то, что вам нужно. Проблема в том, что вы не можете использовать array_unique рекурсивно.
Это еще один способ из комментариев документации PHP.net (замечательные фрагменты кода)
function arrayUnique($myArray) { if(!is_array($myArray)) return $myArray; foreach ($myArray as &$myvalue){ $myvalue=serialize($myvalue); } $myArray=array_unique($myArray); foreach ($myArray as &$myvalue){ $myvalue=unserialize($myvalue); } return $myArray; }
Вот еще одна идея. Опять же, не очень элегантно, но может быть довольно быстро. Он похож на вторую часть Chacha102, хотя это было бы быстрее, если бы у вас были только целые значения в вспомогательных массивах.
// implode the sub arrays $tmpArray = array(); foreach ($arr as $key => $array) { $tmpArray[$key] = implode(',', $array); } // get only the unique values $tmpArray = array_unique($tmpArray); // explode the values $arr = array(); foreach ($tmpArray as $key => $string) { $arr[$key] = explode(',', $string); }
Хешинг – это хорошая идея, это сделало бы решение O (n) в среднем
В основном вы перебираете через $ arr и делаете хэш всего массива, а затем сравниваете его с предыдущими хэшами, которые вы видели (это O (1), используя isset () или O (m), чтобы быть точным, где m количество элементов во внутреннем массиве). и если есть столкновение, вы сравниваете фактические элементы массива. обычно столкновение означает, что вы видели этот массив раньше, и это дубликат, но это не гарантировано. вот несколько psuedo php, которые реализуют этот алгоритм.
function mkhash($array = array()) { $hash = ""; foreach ($array as $element) { $hash .= md5($element); } } $seen = array(); $newArray = array(); foreach($arr as $elementArray) { $hash = mkhash($elementArray); if(!isset($seen[$hash])) { $newArray[] = $elementArray; $seen[$hash] = $elementArray; } else if(count(array_diff($elementArray, $seen[$hash])) > 0) { $newArray[] = $elementArray; //this is true if two different arrays hashed to the same element } }
Метод хеширования сложнее реализовать, и обработка столкновений должным образом сложна, поэтому существует O (nlogn).
O (nlogn) способ сделать это будет сортировать массив
$arr = array_multisort($arr); //O(nlogn)
И тогда все, что вам нужно сделать, это сравнить соседние массивы, чтобы увидеть, являются ли они дублирующими
Конечно, вы можете просто использовать подход O (n ^ 2) и сравнить каждый внутренний массив с любым другим внутренним массивом …
EDIT: oh и вот еще одна идея O (n), вы можете рекурсивно построить trie, используя ключи массива, которые сопоставляются с другими массивами, поэтому вы получаете массив глубоких m-уровней, где m – самый длинный внутренний массив, который у вас есть. Каждая ветвь trie представляет собой уникальный внутренний массив. Конечно, вам придется написать некоторый служебный код, чтобы преобразовать trie обратно в 2D-массив, поэтому вы не увидите преимущества производительности, пока мощность вашего ввода очень велика!
Это зависит от того, есть ли у вас ресурсы для хранения большего массива в памяти (так что в основном это зависит от того, хотите ли вы только уникальные значения, чтобы предотвратить его раздувание во время цикла или если вам просто нужен конечный результат, чтобы быть массивом уникальные значения.
Для всех примеров я предполагаю, что вы получаете значения для входа в большой массив из какого-то внешнего источника, например запроса MySQL.
Чтобы предотвратить дублирование в главном массиве:
Вы можете создать два массива, один со значениями в виде строки, один со значениями как фактические значения массива.
while($row = $results->fetch_assoc) { $value_string = implode("," $row); if(in_array($value_string, $check_array) { $check_array[] = $value_string; $master_array[] = $row; } }
В приведенном выше примере он просто видит, что строковая версия вашего набора данных находится в массиве наборов строковых данных, которые уже выполнялись. Вы получаете большие накладные расходы с двумя массивами, но никогда не получаете повторяющихся значений.
Или, как уже упоминалось, я уверен, что есть array_unique
, который происходит после ввода всех данных. Изменив приведенный выше пример, вы получите
while($row = $results->fetch_assoc) { $master_array[] = $row; } $master_array = array_unique($master_array);