我有一个关联数组的索引数组,如下所示:
[
['brand' => 'ABC', 'model' => 'xyz', 'size' => 13],
['brand' => 'QWE', 'model' => 'poi', 'size' => 23],
['brand' => 'ABC', 'model' => 'xyz', 'size' => 18]
];
我需要减少/合并/重组数据以基于
brand
和 model
进行分组。如果在对这两列进行分组时, brand
和 model
组合出现多次,则 size
值应形成索引子数组。否则,size
值可以保留为单个字符串值。
我想要的结果:
[
['brand' => 'ABC', 'model' => 'xyz', 'size' => [13, 18]],
['brand' => 'QWE', 'model' => 'poi', 'size' => 23],
];
就算法而言,你只需要:
创建一个空数组。
扫描源数组中的每个数组元素,为遇到的每个新品牌/型号创建一个新元素(在空数组中),并添加尺寸子数组。
如果已经有品牌/型号条目,只需将尺寸添加到子数组中(如果尚不存在)。
您可以按如下方式实现(粗略,但它有效):
<?php
// Test data.
$sourceArray = array(array('brand'=>'ABC', 'model'=>'xyz', 'size'=>13),
array('brand'=>'QWE', 'model'=>'poi', 'size'=>23),
array('brand'=>'ABC', 'model'=>'xyz', 'size'=>18),
);
$newArray = array();
// Create a new array from the source array.
// We'll use the brand/model as a lookup.
foreach($sourceArray as $element) {
$elementKey = $element['brand'] . '_' . $element['model'];
// Does this brand/model combo already exist?
if(!isset($newArray[$elementKey])) {
// No - create the new element.
$newArray[$elementKey] = array('brand'=>$element['brand'],
'model'=>$element['model'],
'size'=>array($element['size']),
);
}
else {
// Yes - add the size (if it's not already present).
if(!in_array($element['size'], $newArray[$elementKey]['size'])) {
$newArray[$elementKey]['size'][] = $element['size'];
}
}
}
// *** DEBUG ***
print_r($newArray);
?>
顺便说一下,为了方便访问,我将 size 子数组设置为始终是一个数组。 (即:您不必允许它可能只是一个元素。)
//$array is the array in your first example.
foreach($array as $item) {
$itemname = $item["brand"] . "_" . $item["model"]
$new_array[$itemname]["brand"] = $item["brand"];
$new_array[$itemname]["model"] = $item["model"];
$new_array[$itemname]["size"][] = $item["size"];
}
“升级”到 knarf 的片段....
foreach($array as $item) {
$itemname = $item["brand"] . "_" . $item["model"]
$new_array[$itemname]["brand"] = $item["brand"];
$new_array[$itemname]["model"] = $item["model"];
$new_array[$itemname]["size"][ $item["size"] ] = 1;
}
foreach($new_array as $itemname=>$data) {
if(isset($data['size']) && is_array($data['size'])) {
$new_array[$itemname]['size']=array_keys($new_array[$itemname]['size']);
}
}
不再有重复...
我将从字面上解释这个问题并提供准确描述的输出结构。
临时复合键允许非常快速地查找以前遇到的
brand
- model
对。重要的是,使用分隔字符(不在两个值中使用)来分隔复合字符串中的每个值,这样就不会出现意外的“数据冲突”。
如果给定的“品牌-型号”组合仅出现一次,则原始行结构将被推入结果数组中。否则,“大小”数据将转换为索引数组,并将后续唯一大小值推入子数组中。
经典
foreach()
:(演示)(使用array_unique删除潜在重复大小)
$result = [];
foreach ($array as $row) {
$compositeKey = $row['brand'] . '_' . $row['model'];
if (!isset($result[$compositeKey])) {
$result[$compositeKey] = $row;
} else {
$result[$compositeKey]['size'] = array_merge(
(array)$result[$compositeKey]['size'],
[$row['size']]
);
}
}
var_export($result);
使用
array_reduce()
进行函数式编程:(演示)
var_export(
array_values(
array_reduce(
$array,
function ($carry, $row) {
$compositeKey = $row['brand'] . '_' . $row['model'];
if (!isset($carry[$compositeKey])) {
$carry[$compositeKey] = $row;
} else {
$carry[$compositeKey]['size'] = array_merge(
(array)$carry[$compositeKey]['size'],
[$row['size']]
);
}
return $carry;
}
)
)
);
如果我说实话,我会为我的输出创建一个一致的数据结构,并且大小始终是一个子数组。以下是如何修改上面的代码片段,以在第一次遇到时将 size 元素转换为数组,并将所有随后遇到的 size 值推送到该组的子数组中:(Demo)
$result = [];
foreach ($array as $row) {
$compositeKey = $row['brand'] . '_' . $row['model'];
if (!isset($result[$compositeKey])) {
$row['size'] = (array)$row['size'];
$result[$compositeKey] = $row;
} else {
$result[$compositeKey]['size'][] = $row['size'];
}
}
var_export(array_values($result));