У Python есть хорошая функция zip()
. Есть ли эквивалент PHP?
Есть ли функция php, такая как python zip?
Ответ 1
Пока все массивы имеют одинаковую длину, вы можете использовать array_map
с null
в качестве первого аргумента.
array_map(null, $a, $b, $c, ...);
Если некоторые из массивов короче, они будут дополнены нулями до длины самого длинного, в отличие от python, где возвращаемый результат - длина самого короткого массива.
Ответ 2
Попробуйте эту функцию для создания массива массивов, подобных Pythons zip
:
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;
}
Вы можете передать эту функцию столько, сколько хотите, сколько угодно элементов.
Ответ 3
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;
}
Ответ 4
Этот работает точно так же, как функция Python zip()
, и также совместим с 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);
};
Он объединяет массивы так, как это делает Python zip()
, и не возвращает элементы, найденные после достижения конца самого короткого массива.
Следующее:
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).
Ответ 5
Решение
Решение, соответствующее 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)
?
Как уже упоминалось в моем комментарии, я склоняюсь к решению nabnabit (array_map(null, $a, $b, ...)
), но слегка измененным образом (показано выше).
В общем случае:
array_map(null, $a, $b, $c);
является аналогом для Python's:
itertools.izip_longest(a, b, c, fillvalue=None)
(оберните его в list()
, если вам нужен список вместо итератора). Из-за этого он точно не соответствует требованию для имитации поведения zip()
(если все массивы не имеют одинаковой длины).
Ответ 6
Я написал функции 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>';
Ответ 7
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;
}
Ответ 8
// 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>';
Ответ 9
вы можете увидеть способ array_map
:
$arr1 = ['get', 'method'];
$arr2 = ['post'];
$ret = array_map(null, $arr1, $arr2);
выход:
[['get', 'method'], ['post', null]]
Ответ 10
Вы можете найти zip, а также другие функции Python в Нестандартная библиотека PHP. Включая операторский модуль и defaultarray.
use function nspl\a\zip;
$pairs = zip([1, 2, 3], ['a', 'b', 'c']);
Ответ 11
Чтобы преодолеть проблемы с передачей одного массива в map_array
, вы можете передать эту функцию... к сожалению, вы не можете передать "array"
, поскольку это не настоящая функция, а встроенная вещь.
function make_array() { return func_get_args(); }
Ответ 12
Посвященный тем, кто считает, что это должно быть связано с 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));
}