【问题标题】:Filter 2 dimensions array and merge different values in PHP过滤二维数组并在 PHP 中合并不同的值
【发布时间】:2016-01-30 10:25:45
【问题描述】:

我有一个数组:

$arr = [
  ['id'=>1, 'name'=>'Peter', 'age'=>28],
  ['id'=>1, 'name'=>'David', 'age'=>28],
  ['id'=>2, 'name'=>'John', 'age'=>34],
  ['id'=>3, 'name'=>'Smith', 'age'=>36],
  ['id'=>3, 'name'=>'Smith', 'age'=>28],
];

我想按列“id”过滤它,并合并不同的值。我需要输出:

$arr = [
  ['id'=>1, 'name'=>'Peter,David', 'age'=>28],
  ['id'=>2, 'name'=>'John', 'age'=>34],
  ['id'=>3, 'name'=>'Smith', 'age'=>'36,28']
];

是否有任何 PHP 函数(例如:array_filter、array_walk、array_map、...)可以做到这一点,而无需循环代码如下?

function combine_row($arr){
    $last = null;
    foreach ($arr as $key => $a){
        if ($a['id']==$last['id']){
            foreach ($a as $k=>$v) {
                if($v!==$last[$k]) {
                     $arr[$key][$k].=','.$last[$k];
                }
            }
            unset($arr[$key-1]);
        }
        $last = $a;
    }
    return $arr;
}

谢谢你帮助我!

【问题讨论】:

  • Phong,你解决了吗?让我知道我是否应该更改我的答案
  • 对不起迈克尔,我没有回来查看你的答案,因为我找到了使用 Group_concat 从 mysql 步骤修复它的方法。不管怎样,你的回答太完美了。我将其标记为已接受的答案。谢谢!

标签: php arrays filter


【解决方案1】:

这是一个使用更实用风格的解决方案。基本上只是很多内置的array_* 函数。这将确保更少的副作用,使您的代码更不容易出错。

代码首先找到所有唯一的_id_s。然后它过滤数据并最终加入。

$result = array_map(
    function ($id) use ($arr) {
        return array_map(function ($data) {
                if (is_array($data)) return join(",", array_unique($data));
                return $data;
            }, array_reduce(
                array_filter($arr, function ($item) use ($id) { return $id === $item["id"]; }),
                function ($result, $set) { return $result = array_filter(array_merge_recursive($result, $set)); }, [ ]
            )
        );
    }, 
    array_unique(array_column($arr, "id"))
);

print_r($result);

输出:

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Peter,David
            [age] => 28
        )

    [2] => Array
        (
            [id] => 2
            [name] => John
            [age] => 34
        )

    [3] => Array
        (
            [id] => 3
            [name] => Smith
            [age] => 36,28
        )

)

使用a chainable apigithub,您可以获得更具可读性的代码:

$result = arr($arr)
    ->column("id")
    ->unique()
    ->map(
        function ($id) use ($arr) {
            return arr($arr)
                ->filter(function ($item) use ($id) { return $id === $item["id"]; })
                ->reduce(function ($result, $set) { return array_filter(array_merge_recursive($result, $set)); }, [])
                ->map(function ($data) {
                    if (is_array($data)) return arr($data)->unique()->join(",")->toArray();
                    return $data;
                })->toArray();
        }
    )->toArray();

【讨论】:

    【解决方案2】:
    $result = [];
    foreach ($arr as $person) {
        foreach ($person as $key => $value) {
            if ($key == 'id') {
                $result[$person['id']][$key] = $value;
            } else {
                $result[$person['id']][$key][] = $value;
            }
        }
    }
    

    真正的魔力在于$result[$person['id']],它非常自然地将具有相同id 的所有项目分组到相同的结果数组中。这也为多个值创建数组,而不是仅仅连接字符串,这是一种更明智的数据结构。如果您只想要唯一值,请在此处输入array_unique。如果您确实需要用逗号连接项目,请在末尾使用join(',', ..)

    【讨论】:

      【解决方案3】:

      检查下面的代码,

      function getMergerArray($arr) {
          $newArr = array();
          foreach ($arr as $key => $value) {
              $id = $value['id'];
              $name = $value['name'];
              $age = $value['age'];
              if (array_key_exists($id, $newArr)) {
                  if (!in_array($name, $newArr[$id]['name'])) {
                      $newArr[$id]['name'][] = $name;
                  }
                  if (!in_array($age, $newArr[$id]['age'])) {
                      $newArr[$id]['age'][] = $age;
                  }
                  continue;
              }
              $newArr[$id]['name'][] = $name;
              $newArr[$id]['age'][] = $age;
          }
          foreach ($newArr as $key => $value) {
              $newArr[$key] = array(
                  'id' => $key,
                  'name' => implode(', ', $value['name']),
                  'age' => implode(', ', $value['age']),
              );
          }
      //    echo '<pre>';
      //    print_r($newArr);
      //    echo '</pre>';
          return $newArr;
      }
      

      【讨论】:

      • 嗨@deceze,为什么这个答案被否决了?这个原因将在我发布新答案时对我有所帮助,并将帮助其他参考此答案的人。提前谢谢你:)
      【解决方案4】:

      试试这个

      function merge_multidimensional($arr) {
      $out = array();
      foreach ($arr as $key => $value){
          $out[] = (object)array_merge((array)$arr2[$key], (array)$value);
      }
      return $out;
      

      }

      【讨论】:

        猜你喜欢
        • 2014-03-12
        • 2016-09-06
        • 2022-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        相关资源
        最近更新 更多