2015-02-22 3 views
0

У меня есть многомерный массив:Как условно объединить многомерный массив

Array 
( 
    [10] => Array 
    (
     [from] => Jack 
     [to] => Terry 
     [Bribe] => 0 
     [Joke_Payment] => 0 
     [Corrupt_Support] => 1 
     [Legitimate_Support] => 0 
     [Obfuscation] => 1 
     [Legal_Enforcement] => 0 
     [Whistleblower] => 0 
    ) 

    [11] => Array 
    (
     [from] => Terry 
     [to] => Jack 
     [Bribe] => 0 
     [Joke_Payment] => 0 
     [Corrupt_Support] => 1 
     [Legitimate_Support] => 0 
     [Obfuscation] => 0 
     [Legal_Enforcement] => 1 
     [Whistleblower] => 0 
    ) 
) 

Я хочу, чтобы обновить выше массив нравится: есть 1 (идущий from от to к) и а -1 для противоположного направления, 2 означают для «обоих направлениях.

Array ( [10] => Array 
     (
      [from] => Jack 
      [to] => Terry 
      [Bribe] => 0 
      [Joke_Payment] => 0 
      [Corrupt_Support] => 2 
      [Legitimate_Support] => 0 
      [Obfuscation] => 1 
      [Legal_Enforcement] => -1 
      [Whistleblower] => 0 
     ) } 

Как я могу во-первых, рассчитать их пересекаются, а затем обновить исходный массив?

Они будут иметь одинаковую сумму с ключами, а когда from соответствует to, а to соответствует from элементам, я хочу объединить эти два массива в один. A '1' используется для обозначения того, что свойство относится к направлению from к to, а -1 указывает, что свойство переходит в обратном направлении (от до from).

Мой текущий код:

$fileRelation = explode("\r", $end); 
$rowsRelation = array_map('str_getcsv', $fileRelation); 
$headerRelation = array_shift($rowsRelation); 
$csvArrRelation = array(); 
$countR = count($headerRelation); 
foreach ($rowsRelation as $key => &$row) { 
    $index = 2;$sum = 0;$sumArr = array(); 
    while ($index < $countR) { 
     if ($row[$index]>0) { 
      $sumArr[$sum]=$index; //store row $headerRelation index 
      $sum++; 
     } 
     $index++; 
    } 
    if($sum > 0){ //remove element if no relationship exist 
     foreach ($csvArrRelation as $k => $a) { 
      if (in_array($row[0], $csvArrRelation[$k]) && in_array($row[1], $csvArrRelation[$k])){ 
       $p = array_values($a);$i = 2;$cp= count($p); 
       while($i < $cp){ 
       if($row[$i] == $p[$i]){ 
        $a[$headerRelation[$i]] += $row[$i]; 
       }else{ 
        $a[$headerRelation[$i]] -= $row[$i]; 
       } 
       $i++; 
      } 
       unset($rowsRelation[$key]); 
      } 
     } 
     $csvArrRelation[] = array_combine($headerRelation, $row); 
    } 
} 
+0

Вы можете обновить ваш вопросы с некоторыми реальными данными, то есть для $ countR и $ csvArrRelation, просто простые примеры. Было бы легче кому-то помочь вам, если он будет знать структуру данных. Что значит «пересекаться»?Я не могу найти связь между этими двумя массивами и желаемым результатом, поэтому, если можно, объясните это немного лучше. Обратите внимание, что существует функция array_intersect, которая вычисляет пересечение массивов. Http://php.net/manual/en/function.array-intersect.php – Whirlwind

+0

Являются ли массивы гарантированными всегда одинаковыми и одинаковыми количествами ключей? Почему он начинается с '10'? Похоже, что PHP - это неправильное место для этого. – DanMan

+0

Да, они будут иметь одинаковую сумму с ключами, а когда от совпадений до и до совпадений с элементом, я хочу объединить остальные элементы. В качестве примера я нахожу эту часть, поэтому она начинается с 10 – Blair

ответ

1

Я не буду писать это для вас, но вот хороший старт:

$newRelations = []; 
$deletions = []; 
foreach ($rowsRelation as $key1 => $row1) 
{ 
    foreach ($rowsRelation as $key2 => $row2) 
    { 
     // Don't compare with self 
     if ($key1 != $key2) 
     { 
      // Have we found a reverse match? 
      if (
       $row1['from'] == $row2['to'] && 
       $row1['to'] == $row2['from'] 
      ) 
      { 
       $newRelations[] = myMerge($row1, $row2); 
       $deletions[] = $key1; 
       $deletions[] = $key2; 
      } 
     } 
    } 
} 

// Delete old rows 
foreach ($deletions as $deleteKey) 
{ 
    unset($rowsRelation[$deleteKey]); 
} 

// Add in new rows 
$rowsRelation = array_merge($rowsRelation, $newRelations); 

function myMerge(array $row1, array $row2) 
{ 
    // todo 
} 

Моя стратегия, чтобы сравнить каждую строку с любой другой, и если найдено обратное совпадение, мы знаем, что должно произойти слияние. Чтобы избежать повреждения кортежей foreach, я добавляю новое значение массива в другой массив и записываю ключи, которые я хочу удалить из оригинала. Затем они объединяются/удаляются после завершения работы.

0

Я предполагаю, что это какая-то игра, поэтому давайте назовем «игроком 1» игроком, чье имя появляется в поле «from» и «player 2», имя которого отображается в поле «Кому».

В соответствии с тем, что я понял, вы считаете положительные значения игрока 1 и отрицательным для игрока 2. Затем вы суммируете оба значения в записи «от игрока 1 до игрока 2» и отбрасываете запись «от игрока 2 к игроку 1».

Согласно этому правилу, Corrupt_Support должны в конечном итоге со значением 0, а не 2.
В принципе, после слияния ваши записи, вы не сможете отличить без каких-либо действий на всех, и действия, которые отменили друг друга.

Кроме того, нет правила выбора «победителя», т. Е. Который «из» игрока будет сохранен, что приведет к потенциально непрактичным результатам.
Если у вас есть 3 игрока Abe, Боб и Cal, вы можете закончить с любым возможным, например для того
["Abe vs Bob", "Bob vs Cal" and "Cal vs Abe"] или
["Abe vs Bob", "Abe vs Cal" and "Cal vs Bob"].
В последнем случае поиск действий для Боба будет довольно проблематичным.

Теперь, если вы все еще хотите, чтобы сделать это, вот способ, который использует преимущества PHP хэш-таблицы, чтобы ускорить процесс слияния и выбирает «победитель» согласно алфавитному порядку:

// use "from player 1 to player 2" relation as key 
foreach ($relations as $r) $relation_pairs[$r['from'].'+'.$r['to']] = $r; 

// pick the "winners" according to alphabetic order 
ksort ($relation_pairs); 

// merge relations 
while (list($k,$r) = each($relation_pairs)) // this will take elements deletion into account immediately, contrary to foreach 
{ 
    $symetric = $r['to'].'+'.$r['from']; 
    if (isset($relation_pairs[$symetric])) // found a symetric relation 
    { 
     foreach ($relation_pairs[$symetric] as $field=>$value) // combine all numeric fields 
      if (is_numeric ($value)) 
       $relation_pairs[$k][$field] -= $value; 
     unset ($relation_pairs[$symetric]); // get rid of symetric relation 
    } 
} 
$compressed_relations = array_values ($relation_pairs); // get rid of keys 
Смежные вопросы