我有数组
$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'
也存在。你能帮我吗?
更新 这是我的代码示例,但在评论的地方有问题。
$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;
为你做了一些工作,不好的是我的方式需要一个
eval
,这可能很危险,具体取决于你在值中拥有的字符串...
$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;
}
在这里工作得很好。
在线查看:http://sandbox.onlinephpfunctions.com/code/185658700006fe913e6592a7fc51d4cce0db6a68
首先,我正在构建一个可以使用的过滤器数组,然后将其应用到所有行。就这么简单:p
希望有帮助:)
编辑:
重建了功能的一些糟糕部分,删除了
eval
以防止严重的安全风险。
buildFilter
现在返回一个函数,该函数返回一个简单的测试,具体取决于
您设置的操作(您甚至可以定义自定义测试呵呵)ApplyFilter
结果已修改:)这是新代码
$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($op, $val)
{
return function($data) use ($val, $op)
{
switch($op)
{
case '=':
case '==':
return ($data == $val);
case '===':
return ($data === $val);
case '!=':
return ($data != $val);
case '!==':
return ($data !== $val);
case '>':
return ($data > $val);
case '>=':
return ($data >= $val);
case '<':
return ($data < $val);
case '<=':
return ($data <= $val);
default:
throw new Exception('Unknown operand ' . $op);
}
};
};
$filters = array();
foreach($filters_arr as $k => $v)
{
list($key, $op, $val) = $v;
if( !isset($filters[$key]) )
{
$filters[$key] = $buildFilter($op, $val);
}
else
{
if( !is_array($filters[$key]) )
{
$filters[$key] = array($filters[$key]);
}
$filters[$key][] = $buildFilter($op, $val);
}
}
/*
* Filter function
*/
$applyFilter = function($row, $fk, $fv)
{
// Key not found in row
if( !array_key_exists($fk, $row) )
{
return false;
}
// Get row[key] value
$val = $row[$fk];
// if we have multiple tests for the filter it's an OR
if( is_array($fv) )
{
foreach($fv as $ft)
{
if( $ft($val) === true ) return true; // return true if filter passed
// or continue if not
}
}
else
{
if( $fv($val) === true ) return true; // return true if filter passed
}
// if no filter passed, return false
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;
}
所以不用帮你写代码,直接看一下PHP的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;
});