按第二个数组中的值过滤数组

时间:2017-11-27 03:16:56

标签: php arrays filter array-filter

**我编辑了这个,以显示我如何使用array_search

使我的代码工作

我有一个数组,$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的交集。

4 个答案:

答案 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 );
} );

View this example on eval.in

但是,您的问题似乎表明此数据可能来自数据库;那是对的吗?如果是这样,也许在数据库级别预过滤结果会更有效。通过在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_column id 列的值提取到数组中
  • array_intersect 返回$ arr1 ['id']和$ arr2
  • 中的元素
  • 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]);;
    }