我有一个数组,$arr1
有5列,如下:
key id name style age whim
0 14 bob big 33 no
1 72 jill big 22 yes
2 39 sue yes 111 yes
3 994 lucy small 23 no
4 15 sis med 24 no
5 16 maj med 87 yes
6 879 Ike larg 56 no
7 286 Jed big 23 yes
此数组位于缓存中,而不是数据库中。
然后我有第二个数组,其中包含一个id值列表 -
$arr2 = (0=>14, 1=>72, 2=>8790)
如何过滤$arr1
,以便仅返回ID值为$arr2
的行?
我的代码工作原理如下:
$arr1 = new CachedStuff(); // get cache
$resultingArray = []; // create an empty array to hold rows
$filter_function = function ($row) use ($arr2) {
return (array_search($row['id'], $arr2));
};
$resultingArrayIDs = $arr1->GetIds($filter_function, $resultingArray);
这给了我两个输出:$ resulArray& $ resulArrayIDs,它们都代表$ arr1和$ arr2的交集。
答案 0 :(得分:2)
如果我已正确理解您的问题和数据结构,那么应该这样做:
$dataArray = [
[ 'key' => 0, 'id' => 14 , 'name' => 'bob' , 'style' => 'big' , 'age' => 33 , 'whim' => 'no' ],
[ 'key' => 1, 'id' => 72 , 'name' => 'jill' , 'style' => 'big' , 'age' => 22 , 'whim' => 'yes' ],
[ 'key' => 2, 'id' => 39 , 'name' => 'sue' , 'style' => 'yes' , 'age' => 111 , 'whim' => 'yes' ],
[ 'key' => 3, 'id' => 994 , 'name' => 'lucy' , 'style' => 'small' , 'age' => 23 , 'whim' => 'no' ],
[ 'key' => 4, 'id' => 15 , 'name' => 'sis' , 'style' => 'med' , 'age' => 24 , 'whim' => 'no' ],
[ 'key' => 5, 'id' => 16 , 'name' => 'maj' , 'style' => 'med' , 'age' => 87 , 'whim' => 'yes' ],
[ 'key' => 6, 'id' => 879 , 'name' => 'Ike' , 'style' => 'larg' , 'age' => 56 , 'whim' => 'no' ],
[ 'key' => 7, 'id' => 286 , 'name' => 'Jed' , 'style' => 'big' , 'age' => 23 , 'whim' => 'yes' ]
];
$filterArray = [14, 72, 879];
$resultArray = array_filter( $dataArray, function( $row ) use ( $filterArray ) {
return in_array( $row[ 'id' ], $filterArray );
} );
但是,您的问题似乎表明此数据可能来自数据库;那是对的吗?如果是这样,也许在数据库级别预过滤结果会更有效。通过在SELECT查询中添加一个字段来表示一个布尔值,无论一行是否与您的过滤器ID匹配,或者根本不返回其他行。
答案 1 :(得分:2)
在第二个/过滤阵列上使用迭代检查的麻烦在于,随着阵列大小的增加,它将失去效率。
通过为第一个数组分配新键,并将过滤数组的值翻转到键,您可以在数组上运行一次性过滤器/交叉,然后重新索引输出数组。
我的方法调用没有foreach()
循环,没有迭代条件。
代码:(Demo)
$arr1=[
['key'=>0,'id'=>14,'name'=>'bob','style'=>'big','age'=>33,'whim'=>'no'],
['key'=>1,'id'=>72,'name'=>'jill','style'=>'big','age'=>22,'whim'=>'yes'],
['key'=>2,'id'=>39,'name'=>'sue','style'=>'yes','age'=>111,'whim'=>'yes'],
['key'=>3,'id'=>994,'name'=>'lucy','style'=>'small','age'=>23,'whim'=>'no'],
['key'=>4,'id'=>15,'name'=>'sis','style'=>'med','age'=>24,'whim'=>'no'],
['key'=>5,'id'=>16,'name'=>'maj','style'=>'med','age'=>87,'whim'=>'yes'],
['key'=>6,'id'=>879,'name'=>'Ike','style'=>'larg','age'=>56,'whim'=>'no'],
['key'=>7,'id'=>286,'name'=>'Jed','style'=>'big','age'=>23,'whim'=>'yes']
];
$arr2=[14,72,879];
$arr1=array_column($arr1,null,'id'); // generate temporary keys
//var_export($arr1);
$arr2=array_flip($arr2); // move values to keys
//var_export($arr2);
$filtered=array_intersect_key($arr1,$arr2); // retain subarrays that qualify
//var_export($filtered);
$reindexed=array_values($filtered); // reindex array
var_export($reindexed);
或写成这样的单行:
var_export(array_values(array_intersect_key(array_column($arr1,null,'id'),array_flip($arr2))));
输出:
array (
0 =>
array (
'key' => 0,
'id' => 14,
'name' => 'bob',
'style' => 'big',
'age' => 33,
'whim' => 'no',
),
1 =>
array (
'key' => 1,
'id' => 72,
'name' => 'jill',
'style' => 'big',
'age' => 22,
'whim' => 'yes',
),
2 =>
array (
'key' => 6,
'id' => 879,
'name' => 'Ike',
'style' => 'larg',
'age' => 56,
'whim' => 'no',
),
)
答案 2 :(得分:1)
一种方法是foreach
循环使用array_search()
$result = [];
foreach ($arr1 as $value) { // Loop thru $arr1
if (array_search($value['id'], $arr2) !== false) { // Check if id is in $arr2
$result[] = $value; // Push to result if true
}
}
// print result
print_r($result);
答案 3 :(得分:1)
正如@DecentDabbler所提到的 - 如果数据来自数据库,使用 WHERE 上的 IN 将允许您仅检索相关数据。
过滤的另一种方法是使用数组函数
array_flip 翻转生成的数组,以便$ arr1中的索引表示$ arr1和$ arr2中的元素
$arr1 = [ [ 'id' => 14, 'name' => 'bob'],
['id' => 72, 'name' => 'jill'],
['id' => 39, 'name' => 'sue'],
['id' => 994, 'name' => 'lucy'],
['id' => 879, 'name'=> 'large']];
$arr2 = [ 14,72,879 ];
$intersection = array_flip(array_intersect(array_column($arr1,'id'),$arr2));
foreach ($intersection as $i) {
var_dump($arr1[$i]);;
}