Intereting Posts
Как отказаться от оплаты Paypal, если не из данного места проживания? Доктрина 2: результат запроса как ассоциативный массив Вызов функции-члена на не-объекте шаг копирования, написанный на stackoverflow, для установки FFMPEG на неработающий wamp Многомерный массив – как получить определенные значения из подматрицы PHP Специальная функция SMTP-почты Возврат ERROR fputs send bytes failed errno = 32 Разбитая труба Безопасное всплывающее окно возможно? jTable jQuery плагин Почему моя MySQL хранится процедура не работает? Не получать конкретный результат без брекетов Как отправить данные файла в качестве параметра post в почтовом вызове BuzzBrowser Возможно ли динамически перезагрузить PHP-код во время работы скрипта? Временная метка Unix для дней, часов, минут Nginx и PHP-cgi – не могут file_get_contents любого веб-сайта на сервере Остановить кеширование для PHP 5.5.3 в MAMP move_uploaded_file, создающий недопустимые (403 запрещенные) файлы в nginx

Как работает array_diff?

Как работает array_diff() ? Очевидно, он не мог работать следующим образом:

 function array_diff($arraya, $arrayb) { $diffs = array(); foreach ($arraya as $keya => $valuea) { $equaltag = 0; foreach ($arrayb as $valueb) { if ($valuea == $valueb) { $equaltag =1; break; } } if ($equaltag == o) { $diffs[$keya]=$valuea; } } return $diffs; } //couldn't be worse than this а function array_diff($arraya, $arrayb) { $diffs = array(); foreach ($arraya as $keya => $valuea) { $equaltag = 0; foreach ($arrayb as $valueb) { if ($valuea == $valueb) { $equaltag =1; break; } } if ($equaltag == o) { $diffs[$keya]=$valuea; } } return $diffs; } //couldn't be worse than this 

Кто-нибудь знает лучшее решение?

EDIT @animuson:

 function array_diff($arraya, $arrayb) { foreach ($arraya as $keya => $valuea) { if (in_array($valuea, $arrayb)) { unset($arraya[$keya]); } } return $arraya; } с function array_diff($arraya, $arrayb) { foreach ($arraya as $keya => $valuea) { if (in_array($valuea, $arrayb)) { unset($arraya[$keya]); } } return $arraya; } 

ОБНОВИТЬ

  • см. ниже для более быстрого / лучшего кода.

  • поведение array_diff намного лучше в php 5.3.4, но все же ~ 10 раз медленнее, чем функция Лео.

  • также стоит отметить, что эти функции не являются строго эквивалентными array_diff поскольку они не поддерживают ключи массива, то есть my_array_diff(x,y) == array_values(array_diff(x,y)) .

/ОБНОВИТЬ

Лучшее решение – использовать хэш-карты

 function my_array_diff($a, $b) { $map = $out = array(); foreach($a as $val) $map[$val] = 1; foreach($b as $val) if(isset($map[$val])) $map[$val] = 0; foreach($map as $val => $ok) if($ok) $out[] = $val; return $out; } $a = array('A', 'B', 'C', 'D'); $b = array('X', 'C', 'A', 'Y'); print_r(my_array_diff($a, $b)); // B, D 

эталонный тест

 function your_array_diff($arraya, $arrayb) { foreach ($arraya as $keya => $valuea) { if (in_array($valuea, $arrayb)) { unset($arraya[$keya]); } } return $arraya; } $a = range(1, 10000); $b = range(5000, 15000); shuffle($a); shuffle($b); $ts = microtime(true); my_array_diff($a, $b); printf("ME =%.4f\n", microtime(true) - $ts); $ts = microtime(true); your_array_diff($a, $b); printf("YOU=%.4f\n", microtime(true) - $ts); с function your_array_diff($arraya, $arrayb) { foreach ($arraya as $keya => $valuea) { if (in_array($valuea, $arrayb)) { unset($arraya[$keya]); } } return $arraya; } $a = range(1, 10000); $b = range(5000, 15000); shuffle($a); shuffle($b); $ts = microtime(true); my_array_diff($a, $b); printf("ME =%.4f\n", microtime(true) - $ts); $ts = microtime(true); your_array_diff($a, $b); printf("YOU=%.4f\n", microtime(true) - $ts); 

результат

 ME =0.0137 YOU=3.6282 

любые вопросы? 😉

и, просто для удовольствия,

 $ts = microtime(true); array_diff($a, $b); printf("PHP=%.4f\n", microtime(true) - $ts); 

результат

 ME =0.0140 YOU=3.6706 PHP=19.5980 

Это невероятно!

user187291 предложение сделать это на PHP через хеш-таблицы просто отлично! В спешке адреналина, взятой из этой фантастической идеи, я даже нашел способ ускорить ее немного (PHP 5.3.1):

 function leo_array_diff($a, $b) { $map = array(); foreach($a as $val) $map[$val] = 1; foreach($b as $val) unset($map[$val]); return array_keys($map); } 

С тестом, взятым из публикации user187291:

 LEO=0.0322 leo_array_diff() ME =0.1308 my_array_diff() YOU=4.5051 your_array_diff() PHP=45.7114 array_diff() 

Задержка производительности array_diff () очевидна даже при 100 записях на массив.

Примечание. Это решение подразумевает, что элементы в первом массиве уникальны (или они станут уникальными). Это типично для хэш-решения.

Примечание . Решение не сохраняет индексы. Назначьте исходный индекс в $ map и, наконец, используйте array_flip () для сохранения ключей.

 function array_diff_pk($a, $b) { $map = array_flip($a); foreach($b as $val) unset($map[$val]); return array_flip($map); } 

PS: Я нашел это, ища какой-то array_diff () paradoxon: array_diff () потребовался в три раза дольше для практически одной и той же задачи, если дважды использовать скрипт.

Лучшее решение, чтобы знать, как это работает, чтобы взглянуть на его исходный код 😉
(Ну, это одна из возможностей открытого исходного кода – и если вы видите некоторую возможную оптимизацию, вы можете отправить патч ;-))

Для array_diff он должен быть в ext/standard что означает, что для PHP 5.3 он должен быть там: branches/PHP_5_3/ext/standard

И, array.c файл array.c выглядит как правдоподобная цель; функция php_array_diff , строка 3381, похоже, соответствует array_diff .

(Удачи, пройдя через код: довольно долго …)

Поскольку это было поднято (см. Ответ @ BurninLeo), как насчет чего-то подобного?

 function binary_array_diff($a, $b) { $result = $a; asort($a); asort($b); list($bKey, $bVal) = each($b); foreach ( $a as $aKey => $aVal ) { while ( $aVal > $bVal ) { list($bKey, $bVal) = each($b); } if ( $aVal === $bVal ) { unset($result[$aKey]); } } return $result; } с function binary_array_diff($a, $b) { $result = $a; asort($a); asort($b); list($bKey, $bVal) = each($b); foreach ( $a as $aKey => $aVal ) { while ( $aVal > $bVal ) { list($bKey, $bVal) = each($b); } if ( $aVal === $bVal ) { unset($result[$aKey]); } } return $result; } 

После выполнения некоторых тестов результаты кажутся приемлемыми:

 $a = range(1, 10000); $b = range(5000, 15000); shuffle($a); shuffle($b); $ts = microtime(true); for ( $n = 0; $n < 10; ++$n ) { array_diff($a, $b); } printf("PHP => %.4f\n", microtime(true) - $ts); $ts = microtime(true); for ( $n = 0; $n < 10; ++$n ) { binary_array_diff($a, $b); } printf("binary => %.4f\n", microtime(true) - $ts); $binaryResult = binary_array_diff($a, $b); $phpResult = array_diff($a, $b); if ( $binaryResult == $phpResult && array_keys($binaryResult) == array_keys($phpResult) ) { echo "returned arrays are the same\n"; } 

Вывод:

 PHP => 1.3018 binary => 1.3601 returned arrays are the same 

Конечно, PHP-код не может работать так хорошо, как C-код, поэтому неудивительно, что PHP-код немного медленнее.

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

 <?php function my_array_diff($a, $b) { $map = $out = array(); foreach($a as $val) $map[$val] = 1; foreach($b as $val) if(isset($map[$val])) $map[$val] = 0; foreach($map as $val => $ok) if($ok) $out[] = $val; return $out; } function leo_array_diff($a, $b) { $map = $out = array(); foreach($a as $val) $map[$val] = 1; foreach($b as $val) unset($map[$val]); return array_keys($map); } function flip_array_diff_key($b, $a) { $at = array_flip($a); $bt = array_flip($b); $d = array_diff_key($bt, $at); return array_keys($d); } function flip_isset_diff($b, $a) { $at = array_flip($a); $d = array(); foreach ($b as $i) if (!isset($at[$i])) $d[] = $i; return $d; } function large_array_diff($b, $a) { $at = array(); foreach ($a as $i) $at[$i] = 1; $d = array(); foreach ($b as $i) if (!isset($at[$i])) $d[] = $i; return $d; } $functions = array("flip_array_diff_key", "flip_isset_diff", "large_array_diff", "leo_array_diff", "my_array_diff", "array_diff"); #$functions = array_reverse($functions); $l = range(1, 1000000); $l2 = range(1, 1000000, 2); foreach ($functions as $function) { $ts = microtime(true); for ($i = 0; $i < 10; $i++) { $f = $function($l, $l2); } $te = microtime(true); $timing[$function] = $te - $ts; } asort($timing); print_r($timing); 

Мои тайминги (PHP 5.3.27-1 ~ dotdeb.0):

 [flip_isset_diff] => 3.7415699958801 [flip_array_diff_key] => 4.2989008426666 [large_array_diff] => 4.7882599830627 [flip_flip_isset_diff] => 5.0816700458527 [leo_array_diff] => 11.086831092834 [my_array_diff] => 14.563184976578 [array_diff] => 99.379411935806 

Три новые функции были найдены по адресу http://shiplu.mokadd.im/topics/performance-optimization/

От PHP: «Возвращает массив, содержащий все записи из массива1, которые не присутствуют ни в одном из других массивов».

Итак, вы просто проверяете array1 на все arrayN, и любые значения в массиве 1, которые не отображаются ни в одном из этих массивов, будут возвращены в новом массиве.

Вам не обязательно даже нужно перебирать все значения array1 . Просто для всех дополнительных массивов, in_array($array1, $value) их значения и проверьте, является ли каждое значение in_array($array1, $value) .