合并嵌套数组的值

时间:2016-07-05 19:17:26

标签: php arrays

正如标题所说我得到的数组看起来像这样:

array (size=376)
  0 => 
    array (size=3)
      'source' => int 0
      'target' => int 47
      'officers' => 
        array (size=1)
          0 => string 'PARKER, Thomas, Sir' (length=19)
  1 => 
    array (size=3)
      'source' => int 0
      'target' => int 104
      'officers' => 
        array (size=1)
          0 => string 'STEVENS, Anne' (length=13)
  2 => 
    array (size=3)
      'source' => int 0
      'target' => int 187
      'officers' => 
        array (size=1)
          0 => string 'PARKER, Thomas, Sir' (length=19)
  3 => 
    array (size=3)
      'source' => int 0
      'target' => int 229
      'officers' => 
        array (size=1)
          0 => string 'GROTE, Byron' (length=12)
  4 => 
    array (size=3)
      'source' => int 0
      'target' => int 244
      'officers' => 
        array (size=1)
          0 => string 'GROTE, Byron' (length=12)
  5 => 
    array (size=3)
      'source' => int 1
      'target' => int 60
      'officers' => 
        array (size=1)
          0 => string 'BASON, John' (length=11)
  6 => 
    array (size=3)
      'source' => int 1
      'target' => int 92
      'officers' => 
        array (size=1)
          0 => string 'HAUSER, Wolfhart, Dr' (length=20)

如果source和target相同,我想在此数组中创建1个值,例如

对此进行了保证:

    5 => 
        array (size=3)
          'source' => int 1
          'target' => int 92
          'officers' => 
            array (size=1)
              0 => string 'BASON, John' (length=11)
      6 => 
        array (size=3)
          'source' => int 1
          'target' => int 92
          'officers' => 
            array (size=1)
              0 => string 'HAUSER, Wolfhart, Dr' (length=20)

我想要

5 => 
            array (size=3)
              'source' => int 1
              'target' => int 92
              'officers' => 
                array (size=1)
                  0 => string 'BASON, John' (length=11)
                  1 => string 'HAUSER, Wolfhart, Dr' (length=20)

我的想法是实现这个目标:

for ($i = 0; $i < count($edges); $i++) {
    for ($j = $i + 1; $j < count($edges); $j++) {
        if($edges[$i]['source']==$edges[$j]['source']&&$edges[$i]['target']==$edges[$j]['target']){
            foreach( $edges[$j]['officers'] as $officer){
                array_push($edges[$i]['officers'], $officer);
            }
            array_splice($edges, $j,1);
        }

    }
}

它似乎是合并但只有2个值,因此不会删除旧值:

我有类似的东西:

 66 => 
    array (size=3)
      'source' => int 24
      'target' => int 103
      'officers' => 
        array (size=2)
          0 => string 'GILAURI, Irakli' (length=15)
          1 => string 'JANIN, Neil' (length=11)
  67 => 
    array (size=3)
      'source' => int 24
      'target' => int 103
      'officers' => 
        array (size=1)
          0 => string 'MORRISON, David' (length=15)

所以它合并了Gilauri和Janin,但没有将Morrison,David加入军官阵容以及Gilauri,Irakli和Janin,Neil在这个阵列中有单独的行,不应该添加。

2 个答案:

答案 0 :(得分:2)

请注意,array_splice每次执行时都会重新键入数组。来自文档:

  

请注意,输入中的数字键不会保留。

即。 array_splice($array, 1, 1)上的$array = [0 => 1, 1 => 2, 2 => 3]会产生[0 => 1, 1 => 3]

因此,当您使用for循环进行迭代时,对于每个已移除的数组元素,索引将比以前更多地指向一个条目。

要按索引删除而不重新加密,请使用unset($edges[$j])代替array_splice()

或者使用foreach循环(通过引用操作实际循环而不是副本):

foreach ($edges as $i => &$edge) {
    for ($j = $i + 1; $j < count($edges); $j++) {
        if ($edge['source'] == $edges[$j]['source'] && $edge['target'] == $edges[$j]['target']) {
            foreach ($edges[$j]['officers'] as $officer) {
                array_push($edge['officers'], $officer);
            }
            array_splice($edges, $j, 1);
        }
    }
}

但我推荐使用unset()替代方案,因为它更快(array_splice总是完全重新创建数组)。

答案 1 :(得分:2)

这类似于其他问题,您可以通过使用子数组中的键作为合并结果中的键来解决此问题。它只是有点不同,因为您需要使用多个密钥来确定应合并哪些记录。

我建议只通过连接这两个键来实现。

foreach ($your_array as $item) {
    $k = "$item[source].$item[target]";
    if (isset($merged[$k])) {
        $merged[$k]['officers'] = array_merge($merged[$key]['officers'], $item['officers']);
    } else {
        $merged[$k] = $item;
    }
}

如果你不喜欢复合键,那么你可以在array_values($merged)之后回到普通的数字键。