【问题标题】:Merge 2 array and into a third new one when a value is same当值相同时,将 2 个数组合并到第三个新数组中
【发布时间】:2020-06-24 15:09:21
【问题描述】:

我有一个名为 job counts 的数组,如下 $job=>

Array
        (
            [0] => Array([count] => 3[yearmonth] => 2019-7)
        
            [1] => Array([count] => 3[yearmonth] => 2019-9)
        
            [2] => Array([count] => 5[yearmonth] => 2019-10))           
    )

第二个日期数组为 $date=>

Array
    ([0] => Array([yearmonth] => 2019-6)
    
     [1] => Array([yearmonth] => 2019-7)
    
     [2] => Array([yearmonth] => 2019-8)
    
     [3] => Array([yearmonth] => 2019-9)
    
     [4] => Array([yearmonth] => 2019-10)
)

作业数组不是连续数组。所以在这里我想要的是如果一个条目在 $date 中可用但在 $job 中不存在,那么创建第三个数组,其中 count = 0 和 yearmonth 值。 类似下面的东西

Array
    ([0] => Array([count] => 0[yearmonth] => 2019-6)
    
     [1] => Array([count] => 3[yearmonth] => 2019-7)
    
     [2] => Array([count] => 0[yearmonth] => 2019-8)
    
     [3] => Array([count] => 3[yearmonth] => 2019-9)
    
     [4] => Array([count] => 5[yearmonth] => 2019-10)
)

【问题讨论】:

  • 只需循环 $date 并检查每个 yearmonth 是否在 $job 中,如果没有则获取 count0 并添加到新数组中。
  • 请始终以var_export() 或json_encoded 字符串的形式发布您的数组数据。
  • 您的问题是“需求转储”。我们始终希望您在 Stack Overflow 上发布问题之前进行详尽的研究和尝试。

标签: php arrays codeigniter


【解决方案1】:

要在迭代 $dates 数组时有效地在 $jobs 数组中搜索日期,请创建一个“查找”数组。

查找应具有表示关系数据的键 (yearmonth)。

使用 $dates 数组中遇到的每个日期,检查 yearmonth 值是否表示为查找中的键 - 如果是,则使用 count 值,如果不是,则设置为 0。

& 变量前的意思是“通过引用修改——这样原始数组就发生了变异,而不需要声明一个新的输出数组。

?? 是“空合并运算符”,如果变量为 null/未声明,则允许使用备用值。

代码:(Demo)

$jobs = [
    ['count' => 3, 'yearmonth' => '2019-7'],
    ['count' => 3, 'yearmonth' => '2019-9'],
    ['count' => 5, 'yearmonth' => '2019-10'],         
];
$dates = [
    ['yearmonth' => '2019-6'],
    ['yearmonth' => '2019-7'],
    ['yearmonth' => '2019-8'],
    ['yearmonth' => '2019-9'],
    ['yearmonth' => '2019-10'],
];

$lookup = array_column($jobs, 'count', 'yearmonth');

foreach ($dates as &$date) {
    $date['count'] = $lookup[$date['yearmonth']] ?? 0;
}

var_export($dates);

输出:

array (
  0 => 
  array (
    'yearmonth' => '2019-6',
    'count' => 0,
  ),
  1 => 
  array (
    'yearmonth' => '2019-7',
    'count' => 3,
  ),
  2 => 
  array (
    'yearmonth' => '2019-8',
    'count' => 0,
  ),
  3 => 
  array (
    'yearmonth' => '2019-9',
    'count' => 3,
  ),
  4 => 
  array (
    'yearmonth' => '2019-10',
    'count' => 5,
  ),
)

或者,如果您要求声明一个新的输出数组并且关联子数组必须与您的问题中的顺序相同,那么这是我对相同技术的调整:

代码:(Demo)

$lookup = array_column($jobs, null, 'yearmonth');

$result = [];
foreach ($dates as $date) {
    $result[] = $lookup[$date['yearmonth']] ?? ['count' => 0] + $date;
}

var_export($result);

查找数组现在包含完整的子数组数据。 array_column() 使用null 作为第二个参数以防止隔离单行,并使用yearmonth 作为第三个参数分配第一级键。

foreach 循环不再“通过引用修改”。空合并运算符仍然用于避免调用isset(),是简洁编写回退数据的理想选择。我在包含count 元素的硬编码数组和$date 数组之间使用“联合运算符”——避免调用array_merge() 或手动编写['yearmonth' => $date['yearmonth']。这是一种合适的合并技术,因为键是唯一的,并且与每个子数组相关。

【讨论】:

    【解决方案2】:

    永远不要低估能够在 php 数组中以非常灵活的方式/方式使用键的能力。

    <?php
    //Copied from mickmackusa
    $jobs = [
        ['count' => 3, 'yearmonth' => '2019-7'],
        ['count' => 3, 'yearmonth' => '2019-9'],
        ['count' => 5, 'yearmonth' => '2019-10'],         
    ];
    $dates = [
        ['yearmonth' => '2019-6'],
        ['yearmonth' => '2019-7'],
        ['yearmonth' => '2019-8'],
        ['yearmonth' => '2019-9'],
        ['yearmonth' => '2019-10'],
    ];
    //End copy
    
    /*
        Make the keys of $jobs be the same as values
        of yearmonth: (This makes it easy to compare later on)
    
        Array
        (
            [0] => Array
                (
                    [count] => 3
                    [yearmonth] => 2019-7
                )
    
            [1] => Array
                (
                    [count] => 3
                    [yearmonth] => 2019-9
                )
    
            [2] => Array
                (
                    [count] => 5
                    [yearmonth] => 2019-10
                )
    
            [2019-7] => Array
                (
                    [count] => 3
                    [yearmonth] => 2019-7
                )
    
            [2019-9] => Array
                (
                    [count] => 3
                    [yearmonth] => 2019-9
                )
    
            [2019-10] => Array
                (
                    [count] => 5
                    [yearmonth] => 2019-10
                )
    
        )
    
    */
    foreach($jobs as $key=>$item) {
        $jobs[$item['yearmonth']] = $item;
    }
    
    //Create a third array $third_arr based on your $jobs and $dates array
    $third_arr = [];
    foreach($dates as $item) {
        $key_value = $item['yearmonth'];
        if (isset($jobs[$key_value]['yearmonth'])) {
            //Available in dates and present in $jobs
            //Just copy values from the $jobs item which relates to this yearmonth
            $third_arr[] = $jobs[$key_value];
        }
        else {
            //Available in dates but not present in $job
            $third_arr[] = ['count'=>0, 'yearmonth'=>$key_value];
        }
    }
    

    第三个数组$third_arr的输出:

    Array
    (
        [0] => Array
            (
                [count] => 0
                [yearmonth] => 2019-6
            )
    
        [1] => Array
            (
                [count] => 3
                [yearmonth] => 2019-7
            )
    
        [2] => Array
            (
                [count] => 0
                [yearmonth] => 2019-8
            )
    
        [3] => Array
            (
                [count] => 3
                [yearmonth] => 2019-9
            )
    
        [4] => Array
            (
                [count] => 5
                [yearmonth] => 2019-10
            )
    
    )
    

    以上代码的压缩版本如下所示:

    foreach($jobs as $key=>$item) {
        $jobs[$item['yearmonth']] = $item;
    }
    $third_arr = [];
    foreach($dates as $item) {
        $kvalue = $item['yearmonth'];
        isset($jobs[$kvalue]['yearmonth']) ? 
        $third_arr[] = $jobs[$kvalue] : $third_arr[] = ['count'=>0, 'yearmonth'=>$kvalue];
    }
    

    【讨论】:

    • @mickmackusa - 我希望没关系我从你那里偷了一些代码 ;-)
    • 我没有被冒犯,但这是我的答案,语法调整得更详细。我不推荐这种三元赋值风格——同样,它太冗长了。我不知道这个答案为研究人员的页面增加了多少价值。
    • 请记住,Stack Exchange 是一个教育和授权人们的地方,同时建立一个不断成熟的知识库。这不是一个为人们提供魔法点的网站。与上述“信号”相比,这些点只是“噪音”。当你考虑发帖时,问问自己是否有一些新的、独特的和有价值的东西可以与研究人员分享。如果没有,请不要发布它。同样,永远不要推荐一个你知道比另一个答案“更糟糕”的解决方案——即使它“有效”。
    • 哦,我不会说这是你的答案。我正在使用两个 foreach 循环设置键,并且您将值放入带有计数的另一个查找数组中。我也在创建一个新数组,因为 OP 要求这样做并且您正在修改当前数组。是的,这是解决同一问题的另一种方法,但我再次不同意您的观点,即这是您的答案。您的钥匙顺序也不正确(我认为这并不重要),但这只是事实。
    • 我不知道你在说什么 FGITW 帖子,但我并不是想以某种方式侮辱你。如果我这样做了 - 我道歉。
    【解决方案3】:

    因此,如果您将count =&gt; 0 添加到$date 数组并在yearmonth 上建立索引,您可以在yearmonth 上索引$job 并将其合并到$date

    $result = array_merge(array_column(array_map(function($v) { $v['count'] = 0; return $v; },
                                       $date), null, 'yearmonth'),
                          array_column($job, null, 'yearmonth'));
    

    【讨论】:

    • 虽然这是有效的函数式解决方案,但它将进行 4 次数组迭代:(array_map()array_column()array_column(),然后是 array_merge()。这比我提供的解决方案(仅对数组数据进行 2 次迭代)。这不是攻击,只是向 OP 和研究人员解释差异的信息。
    • 是的,只是为了好玩。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    相关资源
    最近更新 更多