我有一系列这样的产品:
$rows = array();
$rows[100] = array(
array('product_id' => 101, 'name' => ''),
array('product_id' => 102, 'name' => ''),
array('product_id' => 103, 'name' => ''),
);
$rows[200] = array(
array('product_id' => 201, 'name' => ''),
array('product_id' => 202, 'name' => ''),
);
$rows[300] = array(
array('product_id' => 301, 'name' => ''),
array('product_id' => 302, 'name' => ''),
array('product_id' => 303, 'name' => ''),
array('product_id' => 304, 'name' => ''),
);
我想这样排序:
$rows[] = array(
array('product_id' => 101, 'name' => ''), //First value from first subArray
array('product_id' => 201, 'name' => ''), //First value from second subArray
array('product_id' => 301, 'name' => ''), //First value from third subArray
array('product_id' => 102, 'name' => ''), //Second value from first subArray
array('product_id' => 202, 'name' => ''), //...
array('product_id' => 302, 'name' => ''),
array('product_id' => 103, 'name' => ''),
array('product_id' => 303, 'name' => ''),
array('product_id' => 304, 'name' => ''),
);
现在我尝试使用此代码执行此操作:
$max_store_products = max(array_map('count', $rows));
$sortedArray = array();
for($j = 0; $j < $max_store_products; $j++)
{
foreach($rows as $store_id => $store_products)
{
$sp = $rows[$store_id][$j];
if(isset($sp))
{
$sortedArray[] = $rows[$store_id][$j];
}
else
unset($rows[$store_id]);
}
}
但这确实需要很长时间,而且也没有给我想要的预期输出。
有没有更简单的方法呢?
答案 0 :(得分:2)
让我们用一个简单的数组来解释:
Array(
0 => Array(1, 4, 7),
1 => Array(2, 5, 8),
2 => Array(3, 6, 9),
)
首先我们array_shift()
将一个匿名函数放入你的数组中,所以你的数组看起来像这样:
Array(
0 => function(){...}
//Your values
1 => Array(1, 4, 7),
2 => Array(2, 5, 8),
3 => Array(3, 6, 9),
)
然后我们调用call_user_func_array()
并应用array_map()
作为回调。这要做的基本上是:
//↓ 'array_map()' callback from 'call_user_func_array()'
array_map(function(){
//Callback from the First array element
// Second Third Fourth
// array element array element array element more elements...
// ↓ ↓ ↓ ↓
}, Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9) /* , ... */);
Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9) /* , ... */
│ │ │ │ │ │ │ │ └─ 3 iteration in 'array_map()' | 3 value
│ │ │ │ │ │ │ └──── 2 iteration in 'array_map()' | 3 value
│ │ │ │ │ │ └─────── 1 iteration in 'array_map()' | 3 value
│ │ │ │ │ │
│ │ │ │ │ └───────────────── 3 iteration in 'array_map()' | 2 value
│ │ │ │ └──────────────────── 2 iteration in 'array_map()' | 2 value
│ │ │ └─────────────────────── 1 iteration in 'array_map()' | 2 value
│ │ │
│ │ └───────────────────────────────── 3 iteration in 'array_map()' | 1 value
│ └──────────────────────────────────── 2 iteration in 'array_map()' | 1 value
└─────────────────────────────────────── 1 iteration in 'array_map()' | 1 value
现在这意味着我们将一次循环遍历所有subArrays,逐个值并将该匿名函数应用于我们循环的所有值。在匿名函数本身,我们基本上只是array_merge()
我们在当前迭代中得到的值到结果数组:
$result = array_merge($result, Array(1, 2, 3)); //First values from each subArray
$result = array_merge($result, Array(4, 5, 6)); //Second values from each subArray
$result = array_merge($result, Array(7, 8, 9)); //Third values from each subArray
//...
<?php
$arr = []; //Your array here
$result = [];
array_unshift($arr, function(...$values)use(&$result){
$result = array_merge($result, array_filter($values));
});
call_user_func_array("array_map", $arr);
print_r($result);
?>
答案 1 :(得分:2)
此解决方案并不依赖于唯一且可排序的数组值。它将通过总是从每个数组中取出一个元素来合并所有数组。
$result = array_filter(array_reduce(array_map(null, ...$rows), 'array_merge' ,[]));
var_dump($rows);
让我们分解一下:
$columns = array_map(null, ...$rows);
当您将null
作为array_map
的第一个参数传递时,它具有与以下相同的行为:
$columns = array_map(function (...$vals) {
return $vals;
}, ...$rows);
这基本上转换$rows
,因此您将获得一个数组数组,其中包含每个部分的第一个,第二个,第三个等元素。传递null
而不是回调可能看起来很奇怪,但它实际上并不像docs中描述的那样。
$rawResult = array_reduce($columns, 'array_merge', []);
在这里,您只需将所有列合并为一个数组。
$result = array_filter($rawResult);
array_filter
会删除所有NULL
条目,以防您的内部数组长度不均匀。
假设您的值有待排序的内容,例如示例中的product_id
,您可以先合并数组,然后对结果进行排序:
$result = array_merge(...$rows);
usort($result, function ($a, $b) {
return $a['product_id'] % 100 - $b['product_id'] % 100 ?: $a['product_id'] - $b['product_id'];
});
var_dump($result); // merged & sorted result
答案 2 :(得分:0)
相当确定这是你想要的:
<?php
$result = [];
// Get the highest number of items in an entry of `$rows`
$maxItems = 0;
foreach($rows as $row) {
if (count($row)>$maxItems) $maxItems = $row;
}
for($ii=0; $ii < $maxItems; $ii++) {
foreach($rows as $row) {
if (isset($row[$ii])) {
$result[] = $row[ii];
}
}
}
?>
您自己的版本失败的原因是因为您有这一行:
if(isset($sp))
但是,$sp
总是在那里定义。 PHP没有类似javascript的undefined
类型,所以一旦你从一个数组中获取一个项目(无论它是否存在),它被定义,抛出一个E_NOTICE
并导致{ {1}}。您应该在PHP中加快错误消息传递,因为这很明显。
就速度而言,你可以做很多事情来改善这一点。你可以:
如果您首先考虑为什么要这样做,并且如果有更好的方法来解决这个问题而不仅仅修复您的循环,那么可能会更好。如果你真的因此而得到不好的表现,因为你需要处理大量的数据,应用程序设计可能需要修复,而不是这个循环。
答案 3 :(得分:-1)
使用,
function array_flatten($array) {
if (!is_array($array)) {
return FALSE;
}
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, array_flatten($value));
}
else {
$result[$key] = $value;
}
}
return $result;
}