如何有条件地合并多维数组

时间:2015-02-22 09:33:56

标签: php arrays

我有一个多维数组:

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(从fromto而在相反方向有-1,2表示“两个方向。” / p>

 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匹配toto匹配from元素时,我想将这两个数组合并为一个。 “1”用于表示该属性在fromto方向上相关,而-1表示该属性反向(来自tofrom)。

我目前的代码是:

$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);
    }
}

2 个答案:

答案 0 :(得分: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循环,我将新数组值添加到不同的数组,并记录我希望从原始数据中删除的键。然后在工作完成后合并/删除它们。

答案 1 :(得分:0)

我认为这是某种游戏,所以让我们打电话给玩家1&#34;名字出现在&#34;来自&#34;场和&#34;球员2&#34;名字出现在&#34; to&#34;字段。

根据我的理解,你认为玩家1的价值为正,而玩家2的价值为负。然后你将&#34;中的两个值从玩家1加到玩家2和#34;记录并丢弃从玩家2到玩家1&#34;记录。

根据该规则,Corrupt_Support最终应为0,而不是2 基本上,在合并你的记录之后,你将无法区分完全没有任何行动和相互取消的行动。

此外,没有规则选择&#34;胜利者&#34;,即&#34;来自&#34;球员将被保留,导致可能不切实际的结果 如果你有3名球员Abe,Bob和Cal,你可以得到任何可能的订单,例如
["Abe vs Bob", "Bob vs Cal" and "Cal vs Abe"]
["Abe vs Bob", "Abe vs Cal" and "Cal vs Bob"]
在后一种情况下,查找Bob的操作会有相当大的问题。

现在,如果你仍然想要这样做,这里有一种方法可以利用PHP哈希表加速合并并选择&#34;赢家&#34;按照字母顺序:

// 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