PHP中两个数组中的一个键的多个值

时间:2018-07-24 13:27:38

标签: php arrays dictionary key key-value

我想结合使用array_combine的2个数组。我希望Array1的值是我的键,而Array2的值是我的值。 这些值来自一个.yml文件,该文件的组件组为键,组件名称为值

   $yamlKeys = array();
    foreach ($yaml['components'] as $yamlComponent) {
        array_push($yamlKeys, $yamlComponent['cachet']['componentgroup']);
    }

    $yamlValues = array();
    foreach ($yaml['components'] as $yamlComponent) {
        array_push($yamlValues, $yamlComponent['cachet']['componentname']);
    }

    $yamlMap = array();
    $yamlMap = array_combine($yamlKeys, $yamlValues);

    echo("===== YAML MAP STARTS =====");
    var_dump($yamlMap);
    echo("===== YAML MAP ENDS =====");  

我的问题: 可以有同名的钥匙。 在$ yamlMap中,只会分配一个值(最后一个)。例如:

Yaml文件看起来像这样:

FOO => BAR
Key1 => Value1
Key2 => Value2
FOO => BAZ
Key3 => Value3  

我的代码可以:

FOO => BAZ
Key1 => Value1
Key2 => Value2
Key3 => Value3  

但是我想要这样:

FOO => BAR, BAZ
Key1 => Value1
Key2 => Value2
Key3 => Value3  

更准确地说:如果有更多的“ FOO”键,我希望“ FOO”具有更多的值(也许是值的数组)。

有什么主意吗?谢谢。

3 个答案:

答案 0 :(得分:0)

您的代码不起作用的原因是因为array_combine需要唯一键。因此,循环是获取期望值的唯一方法。

这是我循环唯一键并使用array_intersect(_key)获取匹配值的一种方法。
如果计数不止一个,我知道输出子数组应该是数组。
否则,它是[0]项目中的单个值(由于array_values),我只添加了它。

$yamlKeys = ["FOO","Key1","Key2","FOO","Key3"];
$yamlValues = ["BAR","Value1","Value2","BAZ","Value3"];

$yamlMap = [];
foreach(array_unique($yamlKeys) as $key => $ykey){
    $temp = array_values(array_intersect_key($yamlValues,array_intersect($yamlKeys, [$ykey])));
    if(count($temp)>1){
        $yamlMap[$ykey] = $temp;
    }else{
        $yamlMap[$ykey] = $temp[0];
    }
}

var_dump($yamlMap);

输出:

array(4) {
  ["FOO"]=>
  array(2) {
    [0]=>
    string(3) "BAR"
    [1]=>
    string(3) "BAZ"
  }
  ["Key1"]=>
  string(6) "Value1"
  ["Key2"]=>
  string(6) "Value2"
  ["Key3"]=>
  string(6) "Value3"
}

https://3v4l.org/hu2re

由于“问题”是FOO键,因此我将解释代码对该键的作用。

代码使用array_intersect查找“ FOO”键并返回:

array(2) {
  [0]=>
  string(3) "FOO"
  [3]=>
  string(3) "FOO"
}

请注意,键与原始数组匹配。
在array_intersect_key中使用它,它使用键编号并使用匹配的键从values数组中获取值。

array(2) {
  [0]=>
  string(3) "BAR"
  [3]=>
  string(3) "BAZ"
}

然后我使用array_values来设置键0、1。
$ temp现在看起来像

array(2) {
  [0]=>
  string(3) "BAR"
  [1]=>
  string(3) "BAZ"
}

由于计数多于一个,if()将为true,并将$ temp-array添加到$ yamlMap的键“ FOO”中。
如果它只是数组中的一项,则只会添加单个字符串,因此不会是多维的

答案 1 :(得分:0)

这是一种更直接的方法:

代码:(Demo)(or this alternative/condensed version

$yamlMap = [];
foreach ($yaml['components'] as $yamlComponent) {
    $key = $yamlComponent['cachet']['componentgroup'];
    $value = $yamlComponent['cachet']['componentname'];
    if (isset($yamlMap[$key])) {
        if (is_array($yamlMap[$key])) {
            $yamlMap[$key][] = $value;  // push to existing array
        } else {
            $yamlMap[$key] = [$yamlMap[$key], $value];  // convert string to array containing old string and new string
        }
    } else {
        $yamlMap[$key] = $value;  // save first occurrence as a string
    }
}

var_export($yamlMap);

输出:

array (
  'FOO' => 
  array (
    0 => 'BAR',
    1 => 'BAZ',
  ),
  'Key1' => 'Value1',
  'Key2' => 'Value2',
  'Key3' => 'Value3',
)

初始解决方案:

迭代一次数据,将其精简为2维数组,然后使用array_merge_recursive()的魔力将其转换为所需的输出。 ...是splat运算符,它告诉array_merge_recursive()$result视为一系列1维数组而不是2维数组。

代码:(Demo

foreach ($yaml as $components) {
    foreach ($components as $sets) {
        foreach ($sets as $cachet) {
            $result[] = [$cachet['componentgroup'] => $cachet['componentname']];
        }
    }
}

var_export(array_merge_recursive(...$result));

我的解决方案从您未曾动过的$yaml变量开始。

$yaml = [
    'components' => [
        [
            'cachet' => [
                'componentgroup' => 'FOO',
                'componentname' => 'BAR'
            ]
        ],
        [
            'cachet' => [
                'componentgroup' => 'Key1',
                'componentname' => 'Value1'
            ]
        ],
        [
            'cachet' => [
                'componentgroup' => 'Key2',
                'componentname' => 'Value2'
            ]
        ],
        [
            'cachet' => [
                'componentgroup' => 'FOO',
                'componentname' => 'BAZ'
            ]
        ],
        [
            'cachet' => [
                'componentgroup' => 'Key3',
                'componentname' => 'Value3'
            ]
        ]
    ]
];

输出:

array (
  'FOO' => 
  array (
    0 => 'BAR',
    1 => 'BAZ',
  ),
  'Key1' => 'Value1',
  'Key2' => 'Value2',
  'Key3' => 'Value3',
)

答案 2 :(得分:-3)

$yamlMap = [];
foreach ($yaml['components'] as $yamlComponent) {
    $key = $yamlComponent['cachet']['componentgroup'];
    $value = $yamlComponent['cachet']['componentname'];
    // Lets initialize the key to be an array so that we may collect multiple values
    if(!array_key_exists($key, $yamlMap)) {
        $yamlMap[$key] = [];
    }
    // lets add the value to the map under the key
    $yamlMap[$key][] = $value;
}

https://3v4l.org/FtjQC