如何按条件筛选数组

32

我有一个像这样的数组:

array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2)

现在我想通过某些条件筛选数组,并保留值等于2的元素,删除所有值不为2的元素。

所以我期望的结果数组应该是:

array("a" => 2, "c" => 2, "f" => 2)

注意:我希望保留原始数组中的键。

如何使用PHP实现?有任何内置函数吗?


请查看array_filter页面上的示例。 - outis
9个回答

56
$fullArray = array('a'=>2,'b'=>4,'c'=>2,'d'=>5,'e'=>6,'f'=>2);


function filterArray($value){
    return ($value == 2);
}

$filteredArray = array_filter($fullArray, 'filterArray');

foreach($filteredArray as $k => $v){
    echo "$k = $v";
}

要求为每个请求创建不同的函数... 是否可以添加额外变量?(将2作为变量)。为每个请求创建不同的函数...是否可以添加额外变量?(将2作为变量)。 - menardmam
2
更新这个答案使用闭包会很好,以教授2019年的最佳实践! - BenMorel

33

你需要通过循环遍历数组并根据条件过滤每个元素。可以使用不同的方法实现。

循环 while / for / foreach 方法

使用任何你想用的循环,比如whileforforeach,遍历数组。然后检查条件,如果元素不符合条件,则使用unset()删除它们或者将符合条件的元素写入新数组中。

循环

//while loop
while(list($key, $value) = each($array)){
    //condition
}

//for loop
$keys = array_keys($array);
for($counter = 0, $length = count($array); $counter < $length; $counter++){
    $key = $keys[$counter];
    $value = $array[$key];
    //condition 
}

//foreach loop
foreach($array as $key => $value){
    //condition
}

条件

只需将您的条件放入循环中,即在注释//condition的位置。条件可以检查任何您想要的内容,然后您可以使用unset()删除不符合条件的元素,并使用array_values()重新索引数组(如果您希望如此),或者将满足条件的元素写入新数组中。

//Pseudo code
//Use one of the two ways
if(<b>condition</b>){  //1. Condition fulfilled
    $newArray[ ] = $value;
            //↑ Put '$key' there, if you want to keep the original keys
            //Result array is: $newArray

} else {        //2. Condition NOT fulfilled
    unset($array[$key]);
    //Use array_values() after the loop if you want to reindex the array
    //Result array is: $array
}

array_filter() 方法

另一种方法是使用内置的 array_filter() 函数。它通常与使用简单循环的方法差不多。

如果你想保留数组中的元素,只需返回 TRUE;如果你想从结果数组中删除元素,则返回 FALSE

//Anonymous function
$newArray = array_filter($array, function($value, $key){
    //condition
}, ARRAY_FILTER_USE_BOTH);

//Function name passed as string
function filter($value, $key){
    //condition
}
$newArray = array_filter($array, "filter", ARRAY_FILTER_USE_BOTH);

//'create_function()', NOT recommended
$newArray = array_filter($array, create_function('$value, $key', '/* condition */'), ARRAY_FILTER_USE_BOTH);

preg_grep() 方法

preg_grep() 类似于 array_filter(),不同之处在于它只使用正则表达式来过滤数组。因此你可能无法做到所有的筛选操作,因为你只能使用正则表达式作为过滤器,并且只能按值或键(使用一些额外代码)进行过滤。

另外请注意,您可以将标志 PREG_GREP_INVERT 作为第三个参数传递以反转结果。

//Filter by values
$newArray = preg_grep("/<b>regex</b>/", $array);

常见条件

有许多常见的条件可用于筛选数组,所有这些条件都可以应用于数组的值和/或键。我在这里只列出了一些:

//<b>Odd values</b>
return $value & 1;

//<b>Even values</b>
return !($value & 1);

//<b>NOT null values</b>
return !is_null($value);

//<b>NOT 0 values</b>
return $value !== 0;

//<b>Contain certain value values</b>
return strpos($value, $needle) !== FALSE;  //Use 'use($needle)' to get the var into scope

//<b>Contain certain substring at position values</b>
return substr($value, $position, $length) === $subString;

//<b>NOT <a rel="noreferrer" href="http://php.net/manual/en/language.types.boolean.php#language.types.boolean.casting">'empty'(link)</a> values</b>
array_filter($array);  //Leave out the callback parameter

它不是通过引用传递 $arr,而是返回一个新数组,而你并没有捕获它。 - Simon
2
@Simon:这份手册不仅仅是给书呆子的。所有开发人员都应该足够聪明和能够阅读它。但也许大多数人期望一个复制粘贴的示例,他们不必思考。 - Gumbo

3
您可以迭代键的副本,以便能够在循环中使用unset()

foreach (array_keys($array) as $key) {
    if ($array[$key] != 2)  {
        unset($array[$key]);
    }
}

这种方法的优点是内存效率高,如果你的数组包含大数值,它们不会被复制。 编辑 我刚刚注意到,你实际上只需要具有值为2的键(你已经知道该值):
$keys = array();
foreach ($array as $key => $value) {
    if ($value == 2)  {
        $keys[] = $key;
    }
}

2

这可以使用闭包来处理。以下答案受到PHP The Right Way的启发:

//This will create an anonymous function that will filter the items in the array by the value supplied
function cb_equal_to($val)
{
    return function($item) use ($val) {
        return $item == $val;
    };
}

$input = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);

// Use array_filter on a input with a selected filter function
$filtered_array = array_filter($input, cb_equal_to(2));
< p > $filtered_array 的内容现在将会是

array ( ["a"] => 2 ["c"] => 2 ["f"] => 2 ) 

2
我认为最简洁、易读的内置函数是:array_intersect()
代码:(演示
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
var_export(array_intersect($array, [2]));

输出:

array (
  'a' => 2,
  'c' => 2,
  'f' => 2,
)

请确保将第二个参数声明为数组,因为这是预期的值类型。
现在写出一个 foreach 循环或使用 array_filter() 都没有问题,只是语法更冗长。
通过向第二个参数数组添加更多值,也可以很容易地扩展 array_intersect()(包括其他“合格”值)。
从PHP7.4开始,箭头函数语法可用。这使得代码更加简洁,并且可以在没有"use"的情况下访问全局变量。
代码:(演示)
$haystack = [
    "a" => 2,
    "b" => 4,
    "c" => 2,
    "d" => 5,
    "e" => 6,
    "f" => 2
];
$needle = 2;

var_export(
    array_filter(
        $haystack,
        fn($v) => $v === $needle
    )
);

2

这应该可以工作,但我不确定它的效率如何,因为您可能最终会复制大量数据。

$newArray = array_intersect_key(
                  $fullarray, 
                  array_flip(array_keys($fullarray, 2))
            );

0
你可以这样做:
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
$arrayFiltered = array_filter($array, function ($element) {
    return $element == 2;
});

或者:

$arrayFiltered = array_filter($array, fn($element) => $element == 2);

0

我可能会做类似这样的事情:

$newarray = array();
foreach ($jsonarray as $testelement){
    if ($testelement == 2){$newarray[]=$testelement}
}
$result = count($newarray);

0
  foreach ($aray as $key => $value) {
    if (2 != $value) {
      unset($array($key));
    }
  }

  echo 'Items in array:' . count($array);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接