【问题标题】:How to filter an array by a condition如何按条件过滤数组
【发布时间】:2010-12-02 23:31:01
【问题描述】:

我有一个这样的数组:

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

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

所以我预期的结果数组是:

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

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

我怎样才能用 PHP 做到这一点?有内置函数吗?

【问题讨论】:

标签: php arrays filter higher-order-functions


【解决方案1】:
$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";
}

【讨论】:

  • 要求为每个请求创建不同的函数...是否可以添加一个额外的 var ? (2 作为变量)
  • 很高兴更新这个答案以使用闭包,在 2019 年教授最佳实践!
【解决方案2】:

您必须以某种方式遍历您的数组并根据您的条件过滤每个元素。这可以通过多种方法来完成。

循环 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(condition){  //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("/regex/", $array);

常见情况

用于过滤数组的常用条件有很多,所有条件都可以应用于数组的值和/或键。我将在这里列出其中的一些:

//Odd values
return $value & 1;

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

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

//NOT 0 values
return $value !== 0;

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

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

//NOT @987654328@ values
array_filter($array);  //Leave out the callback parameter

【讨论】:

  • 它不会通过引用传递 $arr,而是返回一个您没有捕获的新数组。
  • @Simon:这本手册不仅仅适用于书虫。所有开发人员都应该能够并且足够聪明地阅读它。但也许大多数人都希望有一个无需思考的复制粘贴示例。
【解决方案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;
    }
}

【讨论】:

    【解决方案4】:

    我可能会这样做:

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

    【讨论】:

      【解决方案5】:
        foreach ($aray as $key => $value) {
          if (2 != $value) {
            unset($array($key));
          }
        }
      
        echo 'Items in array:' . count($array);
      

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          我认为最快速、可读的内置函数是:array_intersect()

          代码:(Demo)

          $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() 也很容易通过向第二个参数数组添加更多值来扩展(包括额外的“限定”值)。

          【讨论】:

            【解决方案8】:

            这可以使用闭包来处理。以下答案的灵感来自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));
            

            $filtered_array 的内容现在是

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

            【讨论】:

            • 与其从字面上复制其他来源,不如根据问题调整代码,这样答案会更好。
            • @FrankPl 感谢您的建议。我已经编辑了我的答案。
            【解决方案9】:

            你可以这样做:

            $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);
            

            【讨论】:

              猜你喜欢
              • 2021-10-20
              • 1970-01-01
              • 2020-03-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多