改进PHP相关数组

时间:2018-01-15 14:35:57

标签: php arrays

我有一个关联数组:

    $input = [
        ['key'=>'x', 'value'=>'a'],
        ['key'=>'x', 'value'=>'b'],
        ['key'=>'x', 'value'=>'c'],
        ['key'=>'y', 'value'=>'d'],
        ['key'=>'y', 'value'=>'e'],
        ['key'=>'z', 'value'=>'f'],
        ['key'=>'m', 'value'=>'n'],
    ];

我想简单地改革它:

    $output = [
        'x'=>['a','b','c'],
        'y'=>['d','e'],
        'z'=>'f',
        'm'=>'n'
    ]

基本上,条件是:

1. If same key found then put values in an array.
2. If no same key found then value remains string.

如果您对对象更熟悉,可以用对象替换关联数组。

以下是我解决此问题的方法:

    foreach($input as $in){
        if(!empty($output[$in['key']])){
            if(is_array($output[$in['key']])){
                $output[$in['key']][] = $in['value'];
                continue;
            }
            $output[$in['key']] = [$output[$in['key']],$in['value']];
            continue;
        }
        $output[$in['key']] = $in['value'];
    }
    print_r($output);

但我相信它可以以紧凑而有效的方式完成。 如果有人有更好的解决方案,请评论您的答案 非常感谢您的帮助!

4 个答案:

答案 0 :(得分:7)

将数组重新格式化为[[x => a],[x => b],..]并合并所有子数组

$input = array_map(function($x) { return [$x['key'] => $x['value']]; }, $input);
$input = array_merge_recursive(...$input);
print_r($input);

demo

答案 1 :(得分:2)

我建议

<?php

$input = [
    ['key'=>'x', 'value'=>'a'],
    ['key'=>'x', 'value'=>'b'],
    ['key'=>'x', 'value'=>'c'],
    ['key'=>'y', 'value'=>'d'],
    ['key'=>'y', 'value'=>'e'],
    ['key'=>'z', 'value'=>'f'],
    ['key'=>'m', 'value'=>'n'],
];

$reducer = function($carry, $item) {
    $carry[$item['key']][] = $item['value'];

    return $carry;
};

$mapper = function ($item) {
    if (count($item) === 1) {
        return $item[0];
    }

    return $item;
};

$output = array_map($mapper, array_reduce($input, $reducer, []));

var_dump($output);

您可以在此处查看结果:https://3v4l.org/8JjjS

答案 2 :(得分:1)

您可以使用array_reduce循环遍历现有阵列并构建一个新阵列:

$output = array_reduce($input, function ($carry, $i) { 
  $carry[$i['key']][] = $i['value'];
  return $carry;
}, []);

$input中的每个元素都会传递给匿名函数,以及随着我们一起构建的$carry变量。在内部,我们只需将每个value添加到由key索引的子元素中。第三个参数[]是将结果的初始值设置为空数组。

请参阅https://eval.in/935015

(我假设问题中的重复x键是拼写错误,而第二个键应该是z,因为它与您建议的输出匹配)

答案 3 :(得分:0)

对于原始代码,您可能会发现extract()很有趣。我将continue - s替换为else - s,但这更像是一种品味:

foreach($input as $in){
    extract($in);
    if(!empty($output[$key])){
        if(is_array($output[$key])){
            $output[$key][] = $value;
        } else {
            $output[$key] = [$output[$key],$value];
        }
    } else {
        $output[$key] = $value;
    }

另一方面,我可能会使用两个更简单的循环,一个用于构建列表,另一个用于提取单个元素:

foreach($input as $in){
    $output[$in['key']][] = $in['value'];
    /* or:  extract($in);
            $output[$key][]=$value; */
}
foreach($output as $key => $value){
    if(count($value)==1){
        $output[$key]=$value[0];
    }
}