2016-07-05 2 views
0

Как видно из названия говорит, что я получаю массив ищет что-то вроде этого:Присоединяемое значения вложенного массива

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) 

Если источник и цель совпадают Я хочу создать 1 значение в этом массиве, например

Insteed это:

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) 

Итак, это слияние Гилаури и Янина, но не добавило Моррисона, Дэвида в ряды офицеров, а также Гилаури, Иракли и Янина, Нил имеет отдельную строку в этом массиве, которую не следует добавлять.

ответ

2

Обратите внимание, что array_splice выполняет повторное включение массива каждый раз, когда он выполняется. Из документации:

Обратите внимание, что цифровые клавиши на входе не сохраняются.

I.e. на $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 всегда воссоздает массив полностью).

+0

Это действительно очень хорошее объяснение проблемы с кодом OP. –

+0

@bwoebi спасибо, работает как шарм. Я рад, что по крайней мере я был близок к тому, чтобы заставить его работать. – Higeath

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) потом вернуться к подшипникам цифровых клавиш.

+0

Хотя это не объясняет, что он сделал неправильно (см. Мой ответ), это хороший совет; +1. – bwoebi

+0

@bwoebi Спасибо! Мне нравится использовать этот подход для этого типа проблем, поскольку он принимает только один довольно простой проход через входной массив. –

+0

@ Don'tPanic спасибо за помощь, это решение отлично работает! – Higeath

Смежные вопросы