过滤2维数组并在PHP中合并不同的值

时间:2016-01-30 10:25:46

标签: php arrays filter

我有一个数组:

$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;
}

感谢您的帮助!

4 个答案:

答案 0 :(得分:0)

这是一个使用更多功能风格的解决方案。基本上只有很多内置的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();

答案 1 :(得分:0)

$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(',', ..)

答案 2 :(得分:-1)

检查以下代码,

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;
}

答案 3 :(得分:-2)

试试这个

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

}