用另一个数组过滤多维数组

时间:2016-11-28 16:47:08

标签: php arrays multidimensional-array

我有阵列

$rows = [
    ['k'=>1, 'dop1'=>'take', 'dop2' => 'a', 'dat' => '25-11-2016'],
    ['k'=>2, 'dop1'=>'make', 'dop2' => 'b', 'dat' => '26-11-2016'],
    ['k'=>3, 'dop1'=>'sake', 'dop2' => 'c', 'dat' => '27-11-2016'],
    ['k'=>4, 'dop1'=>'bake', 'dop2' => 'd', 'dat' => '28-11-2016'],
    ['k'=>5, 'dop1'=>'dake', 'dop2' => 'e', 'dat' => '29-11-2016'],
    ['k'=>6, 'dop1'=>'jake', 'dop2' => 'f', 'dat' => '30-11-2016'],
    ['k'=>7, 'dop1'=>'ake', 'dop2' => 'g', 'dat' => '24-11-2016']
];

和另一个用于过滤的数组

$filters = [
    ['dat', '=', '27-11-2016'],
    ['dop1', '=', "bake"],
    ['dop1', '=', "sake"],
    ['dop1', '=', "take"],
];

如果重复数组过滤器的第一个元素,它们之间将是OR表达式,否则将是AND表达式。 所以此处的结果必须为['k'=>3, 'dop1'=>'sake', 'dop2' => 'c', 'dat' => '27-11-2016'],因为过滤器数组中存在'dat' => '27-11-2016',而'dop1'=>'sake''dop1'=>'sake'也存在。你能帮帮我吗?

UPDATE 这是我的代码示例,但在注释时会出现问题。

$dop = ['dop1', 'dop2', 'dop3', 'dop4'];
$result = [];

foreach ($rows as $row) {
    foreach ($filters as $filter) {
        if(in_array($filter[0], $dop)){
            $new_filter = [];
            $f = explode("\n", $filter[2]);
            foreach ($f as $item) {
                array_push($new_filter, [$filter[0], $filter[1], $item]);
            }


            if(count($result) == 0){
                foreach ($new_filter as $new) {
                    if($row[$new[0]] == $new[2]){
                        array_push($result, ['r' => $row, 'filter' => $new, 'validity' => 'valid']);
                    }
                }
            } else {
                foreach ($new_filter as $new) {
                    for($i=0;$i<count($result);$i++){
                        if($result[$i]['filter'][0] == $new[0] && $result[$i]['filter'][1] == $new[1] && $result[$i]['filter'][2] != $new[2]){
                            //array_push($result, ['r' => $row, 'filter' => $new, 'validity' => 'valid']);
                        }
                    }
                }
                $invalid = 1;
                $id = 0;
                foreach ($new_filter as $new) {
                    for($i=0;$i<count($result);$i++){
                        if($result[$i]['r'][$new[0]] == $new[2]){
                            $invalid = 0;
                            $id = $i;
                            break 2;
                        }
                    }
                }
                if($invalid == 1){
                    $result[$id]['validity'] = 'invalid';
                }
            }
        } elseif($filter[0] == 'dat') {
            if(count($result) == 0){
                if($row[$filter[0]] == $filter[2]){
                    array_push($result, ['r' => $row, 'filter' => $filter, 'validity' => 'valid']);
                }
            } else {
                if($row[$filter[0]] == $filter[2]){
                    for($i=0;$i<count($result);$i++){
                        if($result[$i]['r'][$filter[0]] != $filter[2]){
                            $result[$i]['validity'] = 'invalid';
                        }
                    }
                }
            }
        }
    }
}
$c = 0;
foreach ($result as $r) {
    if($r['validity'] == 'valid'){
        $c++;
    }
}
echo $c;

2 个答案:

答案 0 :(得分:0)

因此,如果不为您编写代码,请查看PHP's array_filter()

您需要的伪代码如下所示:

var_dump(array_filter($rows, function($row) {
  global $filtered;

  $match = 0;

  foreach ($filtered as $index=>$filter) {
    // run code here to determine if this is an OR or AND and apply matching to the $row
    // $row will be like ['k'=>1, 'dop1'=>'take', 'dop2' => 'a', 'dat' => '25-11-2016'],
    // match based on the index of your $filtered ($index===0 AND, otherwise OR)
  }

  return $match;
});

答案 1 :(得分:0)

为你做了一些工作,不好的是我的方式需要一个grep "command[USEREGEX]" | wc -l这可能是危险的,这取决于你在价值观中的字符串......

eval

在这里工作正常。

在线观看:http://sandbox.onlinephpfunctions.com/code/185658700006fe913e6592a7fc51d4cce0db6a68

首先,我要构建一系列可以使用的过滤器,然后将其应用于所有行。就这么简单:p

希望它有所帮助:)

编辑:

重建该函数的一些糟糕部分,删除$rows = [ ['k'=>1, 'dop1'=>'take', 'dop2' => 'a', 'dat' => '25-11-2016'], ['k'=>2, 'dop1'=>'make', 'dop2' => 'b', 'dat' => '26-11-2016'], ['k'=>3, 'dop1'=>'sake', 'dop2' => 'c', 'dat' => '27-11-2016'], ['k'=>4, 'dop1'=>'bake', 'dop2' => 'd', 'dat' => '28-11-2016'], ['k'=>5, 'dop1'=>'dake', 'dop2' => 'e', 'dat' => '29-11-2016'], ['k'=>6, 'dop1'=>'jake', 'dop2' => 'f', 'dat' => '30-11-2016'], ['k'=>7, 'dop1'=>'ake', 'dop2' => 'g', 'dat' => '24-11-2016'] ]; $filters = [ ['dat', '=', '27-11-2016'], ['dop1', '=', "bake"], ['dop1', '=', "sake"], ['dop1', '=', "take"], ]; function marrfilter($filters_arr, $rows) { /* * Building filters to eval */ $buildFilter = function($key, $op, $val) { switch($op) { case '=': $op = '=='; break; case '==': case '===': case '!=': case '!==': case '>': case '>=': case '<': case '<=': break; default: throw new Exception('Unknown operand'); } $val = addslashes($val); return '$val ' . $op . " '" . $val . "'"; }; $filters = array(); foreach($filters_arr as $k => $v) { list($key, $op, $val) = $v; if( !isset($filters[$key]) ) { $filters[$key] = $buildFilter($key, $op, $val); } else { if( !is_array($filters[$key]) ) { $filters[$key] = array($filters[$key]); } $filters[$key][] = $buildFilter($key, $op, $val); } } /* * Filter function */ $applyFilter = function($row, $fk, $fv) { if( !array_key_exists($fk, $row) ) { return false; } $val = $row[$fk]; if( is_array($fv) ) { $test = false; foreach($fv as $ft) { eval('$test = (' . $ft . ');'); if( $test ) return true; } return false; } else { $test = false; // thats why you realy have to care about what you put in filters and data :) eval('$test = (' . $fv . ');'); if( $test ) return true; } return false; }; /* * Filtering */ $result = array(); foreach($rows as $row) { $r = array(); foreach($filters as $fk => $fv) { $r[] = $applyFilter($row, $fk, $fv); } $r = array_filter($r); if( count($r) == count($filters) ) { $result[] = $row; } } return $result; } 以防止出现极大的安全风险。

  • eval现在返回一个函数,返回一个简单的测试依赖 您设置的操作(您甚至可以定义自定义测试)
  • buildFilter因此修改了:)

这是新代码

ApplyFilter