Python有一个很好的zip()
函数。 PHP有相对应的函数吗?
Python有一个很好的zip()
函数。 PHP有相对应的函数吗?
null
作为第一个参数和array_map
一起使用。array_map(null, $a, $b, $c, ...);
如果一些数组较短,它们将被填充为最长数组的长度,与Python不同,返回结果是最短数组的长度。
array_map
的行为不像 Python 的 zip
。array_map(null, array(1,2), array(3))
返回 array(array(1,3), array(2,null))
,而 zip([1,2], [3])
只返回 [(1,2)]
。 - Gumboarray_map(null,array(1,2,3))
,你并不会像你期望的那样得到array(array(1),array(2),array(3))
,而只是得到原始值的一个数组,即array(1,2,3)
。这可能不会影响大多数人,但如果你试图将任意数量的数组合并在一起(例如,如果数组的数量由对数据库的查询所定义),那么这将变成一个非常令人懊恼的问题。如果使用得当,则是一个不错的解决方案。 - Josiaharray_combine
函数可以实现类似的功能。
否则就自行编写代码实现:
function array_zip($a1, $a2) {
for($i = 0; $i < min(length($a1), length($a2)); $i++) {
$out[$i] = [$a1[$i], $a2[$i]];
}
return $out;
}
尝试使用此函数创建类似于 Python 的 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;
}
您可以使用任意数量的数组以及任意数量的项将此函数传递。
这个与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'))
查看此演示,以证明上述内容。
编辑:添加接收单个参数的支持(在这种情况下,array_map
的行为有所不同;感谢 Josiah)。
array_map()
函数相当不一致的行为:当传递null
作为第一个参数时,它会“压缩”其他参数,但如果只有一个附加参数(除了上述的null
),它不会被封装在array
中(就像有两个或更多的参数那样),而是直接传递。通过检查$params
的长度再添加一个条件可以解决这个问题。 - Tadeckzip()
函数一样,这是不准确的。我只是想指出来,以防其他人使用这种方法遇到相同的问题,希望能够节省他们一些调试时间。特别是因为这里有其他正确处理该情况的答案。 - Josiahif (count($params) === 1) return array_map(function ($elem){return array($elem);},$params[0]);
?我猜这样看起来会好一些,而且代码更简洁。当然,这种方法只适用于 PHP > 5.3,所以这是一个问题。不过没关系,因为我正在使用 PHP 5.3,所以我会采用这种方法。支持改变。 - 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)
?正如我在评论中提到的,我倾向于支持nabnabit的解决方案(array_map(null, $a, $b, ...)
),但稍作修改(如上所示)。
一般来说,这样做:
array_map(null, $a, $b, $c);
是Python中的对应物:
itertools.izip_longest(a, b, c, fillvalue=None)
如果你想要列表而不是迭代器,可以使用list()
将其包装起来。因此,它并不完全符合模仿zip()
的行为的要求(除非所有数组的长度都相同)。
use function nspl\a\zip;
$pairs = zip([1, 2, 3], ['a', 'b', 'c']);
zip()
函数。zip()
和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>';
/**
* Takes an arbitrary number of arrays and "zips" them together into a single
* array, taking one value from each array and putting them into a sub-array,
* before moving onto the next.
*
* If arrays are uneven lengths, will stop at the length of the shortest array.
*/
function array_zip(...$arrays) {
$result = [];
$args = array_map('array_values',$arrays);
$min = min(array_map('count',$args));
for($i=0; $i<$min; ++$i) {
$result[$i] = [];
foreach($args as $j=>$arr) {
$result[$i][$j] = $arr[$i];
}
}
return $result;
}
使用方法:
print_r(array_zip(['a','b','c'],[1,2,3],['x','y']));
输出:
Array
(
[0] => Array
(
[0] => a
[1] => 1
[2] => x
)
[1] => Array
(
[0] => b
[1] => 2
[2] => y
)
)
function zip() {
$zip = [];
$arrays = func_get_args();
if ($arrays) {
$count = min(array_map('count', $arrays));
for ($i = 0; $i < $count; $i++) {
foreach ($arrays as $array) {
$zip[$i][] = $array[$i];
}
}
}
return $zip;
}
// 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>';