Как отфильтровать массив по условию - PullRequest
22 голосов
/ 01 октября 2009

У меня есть такой массив:

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

Теперь я хочу отфильтровать этот массив по некоторому условию и сохранить только те элементы, для которых значение равно 2, и удалить все элементы, для которых значение НЕ равно 2.

Итак, мой ожидаемый массив результатов будет:

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

Примечание. Я хочу сохранить ключи от исходного массива.

Как я могу сделать это с PHP? Какие-нибудь встроенные функции?

Ответы [ 7 ]

46 голосов
/ 01 октября 2009
$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";
}
23 голосов
/ 01 октября 2009

Вы как-то должны пройти через ваш массив и отфильтровать каждый элемент по вашему состоянию. Это можно сделать разными способами.

Петли while / for / foreach метод

Циклически перебирайте массив с любым желаемым циклом, может быть, while, for или foreach. Затем просто проверьте ваше состояние и либо 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 href="http://php.net/manual/en/language.types.boolean.php#language.types.boolean.casting" rel="noreferrer">'empty'(link)</a> values</b>
array_filter($array);  //Leave out the callback parameter
3 голосов
/ 01 октября 2009

Вы можете перебирать копии ключей, чтобы иметь возможность использовать 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 голосов
/ 01 октября 2009

Это должно сработать, но я не уверен, насколько это эффективно, так как вы, вероятно, в конечном итоге скопируете много данных.

$newArray = array_intersect_key(
                  $fullarray, 
                  array_flip(array_keys($fullarray, 2))
            );
1 голос
/ 03 июля 2018

Мне кажется, самая удобная для чтения встроенная функция: 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,
)

Просто убедитесь, что вы объявили 2-й параметр как массив, так как это тип ожидаемого значения.

Теперь нет ничего плохого в написании цикла foreach или использовании array_filter(), у них просто более подробный синтаксис.

array_intersect() также очень легко расширять (включая дополнительные «уточняющие» значения), добавляя дополнительные значения во второй массив параметров.

0 голосов
/ 01 октября 2009
  foreach ($aray as $key => $value) {
    if (2 != $value) {
      unset($array($key));
    }
  }

  echo 'Items in array:' . count($array);
0 голосов
/ 01 октября 2009

Я мог бы сделать что-то вроде:

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