3

我有一个关联数组的索引数组,如下所示:

[
    ['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],
];
4

4 回答 4

3

就算法而言,您只需要:

  1. 创建一个空数组。

  2. 扫描源数组中的每个数组元素,为遇到的每个新品牌/型号创建一个新元素(在空数组中)并添加大小子数组。

  3. 如果已经有品牌/型号条目,则只需将大小添加到子数组中(如果它不存在)。

您可以按如下方式实现它(粗略,但它有效):

<?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);
?>

顺便说一下,为了便于访问,我已经将它的大小子数组始终是一个数组。(即:您不必允许它可能只是一个元素。)

于 2010-08-12T15:05:59.033 回答
0

“升级”到 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']);
  }
}

再也没有重复...

于 2010-08-12T15:33:50.460 回答
0
//$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"];
}
于 2010-08-12T15:12:15.147 回答
0

我将按字面意思解释这个问题,并提供准确描述的输出结构。

临时复合键允许非常快速地查找以前遇到的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));
于 2020-06-14T11:53:05.707 回答