【问题标题】:array_intersect() with 2d arrays in phparray_intersect() 与 php 中的二维数组
【发布时间】:2021-05-29 08:48:17
【问题描述】:

我正在尝试过滤满足两个条件的二维数组。但是,它没有按预期工作。我发现错误在array_intersect() 函数中。为什么array_intersect() 在这里不能正常工作。有没有另一种方法可以在没有迭代的情况下做到这一点。

<?php
            error_reporting(0);
            $students = [
                ["name"=> 'k. l.james', "grade"=>8],
                ["name"=> 'k. l.james', "grade"=>9],
                ["name"=> 'e. musk', "grade"=>8],
                ["name"=> 'jone', "grade"=>9],
            ];
        
            function filterByGrade($grade){
                global $students ;
                if (empty($grade)){
                    return $students ;
                }else{
        
                return array_filter($students , function($record) use($grade){
                    return ($record['grade'] == $grade);
                });
            }
            }
        
            function filterByName($name){
                global $students;
                if (empty($name)){
                    return $students;
                }else{
                
                return array_filter($students, function($record) use($name){
                    return (strcasecmp(str_replace(' ','',$record['name']),str_replace(' ','',$name)) == 0);
                });
            }
            }
            print_r(filterByGrade(8));
            echo "<br/>";
            print_r(filterByName('k.l.james'));
            echo '<br/>';
            print_r(array_intersect(filterByGrade(8), filterByName('k.l.james')));
        ?>
    

结果是;

    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [2] => Array ( [name] => e. musk [grade] => 8 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [1] => Array ( [name] => k. l.james [grade] => 9 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [2] => Array ( [name] => e. musk [grade] => 8 ) )

我希望结果的最后一行是,

    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ))

如果我将array_intersect()中的两个数组如下互换,结果是不同的。

    print_r(array_intersect(filterByName('k.l.james'),filterByGrade(8)));

然后,我得到如下结果。

    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [2] => Array ( [name] => e. musk [grade] => 8 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [1] => Array ( [name] => k. l.james [grade] => 9 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [1] => Array ( [name] => k. l.james [grade] => 9 ) )

我注意到,尽管考虑了两个数组的交集,但仅打印了 array_intersect() 中的第一个过滤数组。

【问题讨论】:

  • 注意:字符串 "k.l.james" 在初始数组中定义为 "k.l.james"

标签: php arrays multidimensional-array array-intersect


【解决方案1】:

您可以创建一个函数来使用多个条件过滤学生,而不是尝试组合 2 个结果。

功能:

/**
 * Here, $condition array of keys/values used to filter $data.
 * ex: ['name' => 'jone', 'grade' => 9]
 */
function filterArray($data, $conditions)
{
    if (empty($conditions)) {
        return $data;
    }
    
    return array_filter($data, function($record) use ($conditions) {
        // Check all given conditions
        foreach ($conditions as $key => $value) {
            // If doesn't match, return false (don't keep in filtered array)
            if ($record[$key] != $value) return false;
        }
        // conditions passed, add to array
        return true;
    });
}

用法:

$students = [
    ["name"=> 'k. l.james', "grade" => 8],
    ["name"=> 'k. l.james', "grade" => 9],
    ["name"=> 'e. musk', "grade" => 8],
    ["name"=> 'jone', "grade" => 9],
];

print_r(filterArray($students, ['grade' => 8]));
// out : [["name"=> 'k. l.james', "grade" => 8],["name"=> 'e. musk', "grade" => 8]]

print_r(filterArray($students, ['name' => 'k. l.james']));
// out : [["name"=> 'k. l.james', "grade" => 8], ["name"=> 'k. l.james', "grade" => 9]]

print_r(filterStudents($students, ['grade' => 8, 'name' => 'k. l.james']));
// out : [["name"=> 'k. l.james', "grade" => 8]]

补充说明:

  • 不鼓励使用global,在下面的代码中,$students 由函数参数给出。
  • 无需在“提前返回”模式 (if ($someCondition) { return; } else { }) 之后使用 else 语句。

【讨论】:

  • 你能评论下面的方法吗
【解决方案2】:

array_intersect() 功能正确,如果内部数组对象被序列化。所以,我得到了正确的结果

print_r(
    array_map('unserialize',
        array_intersect(
            array_map('serialize', filterByName('k.l.james')),
            array_map('serialize', filterByGrade(8))
        )
    )
);

我能否知道对于网站过滤器、@Syscall 的答案或我的方法,什么更有效。

【讨论】:

  • 有趣的答案,但有点复杂 IMO(array_map / 序列化 / 反序列化),并且很难阅读:) 我的答案只允许在学生数组上执行一个循环(使用 array_filter)。无论如何,效率可能取决于数据量和使用情况。
猜你喜欢
  • 2021-10-18
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-05
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
相关资源
最近更新 更多