【问题标题】:Consolidate PHP Array on special Key在特殊键上合并 PHP 数组
【发布时间】:2018-03-30 18:42:36
【问题描述】:

在特殊键上合并数组的最佳做法是什么?

Pseudocode:
If A[i]["name"]==A[j]["name"] and i!=j
then 
{
A[i]["desc"]+=A[j]["desc"] 
array_slice(A,j,1)
}

My Approach:
for ($i=0;$i<count($set);$i++)

{

    for($j=0;$j<count($set);$j++)

    {


        if (($i!=$j) and

            (strcmp($set[$i]["name"],$set[$j]["name"]) == 0))
        {
            $set[$i]["name"].=",".$set[$j]["name"];
            array_slice($set,$j,1)
        }
    }
}

这不像我当前的项目那样工作。相同的实施在其他项目上效果很好。 但我认为有更聪明的方法可以做到这一点。

What it should do:
Before Operation:
A[0]["name"]="Test";
A[0]["desc"]="3,5";

A[1]["name"]="Test";
A[1]["desc"]="8,9";

A[2]["name"]="OtherTest";
A[2]["desc"]="4,3";

After Operation:

A[0]["name"]="Test";
A[0]["desc"]="3,5,8,9";

A[1]["name"]="OtherTest";
A[1]["desc"]="4,3";

【问题讨论】:

  • 能否显示数组的一部分$set
  • 嗯。也许是一个 array_intersect 类型的函数来减少你正在比较的内容?老实说,对我来说,没有什么能真正暗示自己。最终可能会得到一个使用类似循环的解决方案。
  • 我可以看到您正在尝试做什么。问题是 array_slice 实际上并没有从数组中删除任何东西。它只是提取并返回其中的一部分。你可能想做unset($set[$j])。这将删除$j 处的元素。此外,您似乎在连接 name,但您不想将 desc 相互附加吗?
  • $set 看起来像上面的伪代码。
  • 是的 unset() 是我需要的功能

标签: php arrays multidimensional-array associative-array


【解决方案1】:

更简单的逻辑可能是在name 上索引结果:

foreach($A as $values) {
    $desc[$values['name']][] = $values['desc'];
    $result[$values['name']] = $values;
}

然后你可以映射和内爆desc

$result = array_map(function($v) use($desc) {
                        $v['desc'] = implode(',', $desc[$v['name']]);
                        return $v;
                    }, $result);

这会产生:

Array
(
    [Test] => Array
        (
            [name] => Test
            [desc] => 3,5,8,9
        )
    [OtherTest] => Array
        (
            [name] => OtherTest
            [desc] => 4,3
        )
)

要获取数字索引而不是 name 只需重新索引:

$result = array_values($result);

【讨论】:

  • 这对我不起作用,因为我在数组上除了“名称”之外还有其他字段,这些字段必须相同才能合并 desc
  • 那将是相关的信息,不是吗?
  • 已编辑以包含所有键。
【解决方案2】:

这是另一种方法:

$a = [
    ['name' => 'Test', 'desc' => '3,5'],
    ['name' => 'Test', 'desc' => '8,9'],
    ['name' => 'OtherTest', 'desc' => '4,3']
];

$b = [];

$a = array_filter($a, function ($elm) use (&$b) {
    if (isset($b[$elm['name']])) {
        $b[$elm['name']] .= ',' . $elm['desc'];
        return false;
    } else {
        $b[$elm['name']] = '';
        return true;
    }
});

$a = array_map(function ($elm) use ($b) {
    return ['name' => $elm['name'], 'desc' => $elm['desc'] . $b[$elm['name']]];
}, $a);

$a = array_values($a);

var_dump($a);

【讨论】:

    【解决方案3】:

    感谢您的建议。在结合使用 unset() 和 array_vlaues() 的帮助下,我找到了解决问题的方法

    编辑:这似乎非常低效,就像我的这个脚本在中等长度的数组上打破了 30 秒的 phps 标准最大执行时间

    $set[0]["name"]="Test";
    $set[0]["desc"]="3,4";
    $set[1]["name"]="Test";
    $set[1]["desc"]="7,8";
    $set[2]["name"]="OtherTest";
    $set[2]["desc"]="1,2";
    
    for ($i=0;$i<count($set)-1;$i++)
    {
        for($j=0;$j<count($set) ;$j++)
        {
            if (($i!=$j) and (strcmp($set[$i]["name"],$set[$j]["name"]) == 0)) 
            {   
                $set[$i]["desc"].=",".$set[$j]["desc"]; //concat desc
                unset($set[$j]); // remove item at index 0
                $set = array_values($set); // reindex array
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-22
      • 2021-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      相关资源
      最近更新 更多