Есть ли функция php, такая как zip python?

У Python есть хорошая функция zip() . Есть ли эквивалент PHP?

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

 array_map(null, $a, $b, $c, ...); 

Если некоторые из массивов короче, они будут дополнены нулями до длины самого длинного, в отличие от python, где возвращаемым результатом является длина самого короткого массива.

Попробуйте эту функцию, чтобы создать массив массивов, похожий на zip Python:

 function zip() { $args = func_get_args(); $zipped = array(); $n = count($args); for ($i=0; $i<$n; ++$i) { reset($args[$i]); } while ($n) { $tmp = array(); for ($i=0; $i<$n; ++$i) { if (key($args[$i]) === null) { break 2; } $tmp[] = current($args[$i]); next($args[$i]); } $zipped[] = $tmp; } return $zipped; } 

Вы можете передать эту функцию столько, сколько хотите, сколько угодно элементов.

array_combine близок.

Иначе ничего похожего на кодирование:

 function array_zip($a1, $a2) { for($i = 0, $i < min(length($a1), length($a2)); $i++) { $out[$i] = [$a1[$i], $a2[$i]]; } return $out; } 

Это работает точно так же, как функция zip() Python и совместима также с PHP <5.3:

 function zip() { $params = func_get_args(); if (count($params) === 1){ // this case could be probably cleaner // single iterable passed $result = array(); foreach ($params[0] as $item){ $result[] = array($item); }; return $result; }; $result = call_user_func_array('array_map',array_merge(array(null),$params)); $length = min(array_map('count', $params)); return array_slice($result, 0, $length); }; 

Он объединяет массивы так, как это делает zip() Python, и не возвращает элементы, найденные после достижения конца самого короткого массива.

Следующие:

 zip(array(1,2,3,4,5),array('a','b')); 

дает следующий результат:

 array(array(1,'a'), array(2,'b')) 

и следующее:

 zip(array(1,2,3,4,5),array('a','b'),array('x','y','z')); 

дает следующий результат:

 array(array(1,'a','x'), array(2,'b','y')) 

Проверьте эту демонстрацию для доказательства вышеуказанного.

EDIT : добавлена ​​поддержка для приема одного аргумента (в этом случае array_map ведет себя по-другому, спасибо Josiah ).

Решение

Решение, соответствующее zip() очень близко и с использованием встроенных функций PHP в одно и то же время:

 array_slice( array_map(null, $a, $b, $c), // zips values 0, // begins selection before first element min(array_map('count', array($a, $b, $c))) // ends after shortest ends ); 

Почему не просто array_map(null, $a, $b, $c) ?

Как я уже упоминал в своем комментарии , я склоняюсь к решению array_map(null, $a, $b, ...) ( array_map(null, $a, $b, ...) ), но слегка измененным образом (показано выше).

В общем, это:

 array_map(null, $a, $b, $c); 

является аналогом Python's:

 itertools.izip_longest(a, b, c, fillvalue=None) 

(оберните его в list() если вам нужен список вместо итератора). Из-за этого он точно не соответствует требованию для имитации поведения zip() (если все массивы не имеют одинаковой длины).

Я написал функции zip() для моей реализации переименования PHP .
Код был изменен, чтобы использовать стиль zip() в стиле Python, а также стиль Ruby. Разница объясняется в комментариях:

 /* * This is a Python/Ruby style zip() * * zip(array $a1, array $a2, ... array $an, [bool $python=true]) * * The last argument is an optional bool that determines the how the function * handles when the array arguments are different in length * * By default, it does it the Python way, that is, the returned array will * be truncated to the length of the shortest argument * * If set to FALSE, it does it the Ruby way, and NULL values are used to * fill the undefined entries * */ function zip() { $args = func_get_args(); $ruby = array_pop($args); if (is_array($ruby)) $args[] = $ruby; $counts = array_map('count', $args); $count = ($ruby) ? min($counts) : max($counts); $zipped = array(); for ($i = 0; $i < $count; $i++) { for ($j = 0; $j < count($args); $j++) { $val = (isset($args[$j][$i])) ? $args[$j][$i] : null; $zipped[$i][$j] = $val; } } return $zipped; } 

Пример:

 $pythonzip = zip(array(1,2,3), array(4,5), array(6,7,8)); $rubyzip = zip(array(1,2,3), array(4,5), array(6,7,8), false); echo '<pre>'; print_r($pythonzip); print_r($rubyzip); echo '<pre>'; 
 public static function array_zip() { $result = array(); $args = array_map('array_values',func_get_args()); $min = min(array_map('count',$args)); for($i=0; $i<$min; ++$i) { $result[$i] = array(); foreach($args as $j=>$arr) { $result[$i][$j] = $arr[$i]; } } return $result; } 
 // create $a = array("a", "c", "e", "g", "h", "i"); $b = array("b", "d", "f"); $zip_array = array(); // get length of the longest array $count = count(max($a, $b)); // zip arrays for($n=0;$n<$count;$n++){ if (array_key_exists($n,$a)){ $zip_array[] = $a[$n]; } if (array_key_exists($n,$b)){ $zip_array[] = $b[$n]; } } // test result echo '<pre>'; print_r($zip_array); echo '<pre>'; 

вы можете увидеть метод array_map :

 $arr1 = ['get', 'method']; $arr2 = ['post']; $ret = array_map(null, $arr1, $arr2); 

вывод:

 [['get', 'method'], ['post', null]] 

php function.array-map

Вы можете найти zip, а также другие функции Python в нестандартной библиотеке PHP . Включая операторский модуль и defaultarray .

 use function nspl\a\zip; $pairs = zip([1, 2, 3], ['a', 'b', 'c']); 

Чтобы преодолеть проблемы с передачей одного массива в map_array , вы можете передать эту функцию … к сожалению, вы не можете передать "array" поскольку это не настоящая функция, а встроенная вещь.

 function make_array() { return func_get_args(); } 

Посвященный тем, которые чувствуют, что это должно быть связано с array_combine:

 function array_zip($a, $b) { $b = array_combine( $a, $b ); $a = array_combine( $a, $a ); return array_values(array_merge_recursive($a,$b)); }