Извлекать или фильтровать специфические ключи и значения из многомерного массива в другой

#php #arrays #multidimensional-array

#php #массивы #многомерный массив

Вопрос:

Я хочу отфильтровать или сохранить выбранные ключи и их значения в многомерном массиве. Я попробовал несколько методов с array_columns, array_filter и т.д… но я не могу сохранить исходную структуру моего массива.

вот оригинальный пример :

 Array
(
    [0] => Object
        (
            [not_wanted_key1] => some value
            [wanted_key1] => wanted value
            [wanted_key2] => wanted value
            [not_wanted_key3] => some value
            [wanted_key3] => wanted value



       )

    [1] => Object
        (
            [not_wanted_key1] => some value
            [wanted_key1] => wanted value
            [wanted_key2] => wanted value
            [not_wanted_key3] => some value
            [wanted_key3] => wanted value
        )
)
  

ожидаемый результат :

 Array
(
    [0] => Object
        (
            [wanted_key1] => wanted value
            [wanted_key2] => wanted value
            [wanted_key3] => wanted value
       )

    [1] => Object
        (
            [wanted_key1] => wanted value
            [wanted_key2] => wanted value
            [wanted_key3] => wanted value
        )
)
  

Кто-нибудь может меня направить?

Комментарии:

1. Короче говоря, вы не можете, потому что это объекты, а не подмассивы.

Ответ №1:

Вы можете сделать это следующим образом:

 //test data
$array[] = new stdClass;
$array[0]->not_wanted_key1 = '1';
$array[0]->not_wanted_key2 = '3';
$array[0]->wanted_key1 = '4';
$array[0]->wanted_key2 = '5';
$array[0]->wanted_key3 = '6';

print_r($array);


$map = array_flip(['wanted_key1', 'wanted_key2', 'wanted_key3']);

$res = array_map(function($item) use ($map){
    return array_intersect_key((array) $item, $map);
}, $array);


print_r($res);
  

Вывод

 //input array
Array
(
    [0] => stdClass Object
        (
            [not_wanted_key1] => 1
            [not_wanted_key2] => 3
            [wanted_key1] => 4
            [wanted_key2] => 5
            [wanted_key3] => 6
        )

)
//output array
Array
(
    [0] => Array
        (
            [wanted_key1] => 4
            [wanted_key2] => 5
            [wanted_key3] => 6
        )

)
  

Песочница

Довольно просто, хитрость заключается в (array) приведении объекта к массиву, а затем мне нравится использовать array_intersect_key , но мне лень делать это вручную $map , поэтому я просто переворачиваю значения, чтобы они были ключами.

Таким образом, вы можете легко добавлять / удалять ключи, которые хотите сохранить, просто добавив / удалив их из $map .

Если вы хотите сохранить внутренний массив как объект, вы также можете преобразовать его обратно! так что измените это:

  return array_intersect_key((array) $item, $map);
  

Для

  return (object)array_intersect_key((array) $item, $map);
  

Вывод

 Array
(
    [0] => stdClass Object
        (
            [wanted_key1] => 4
            [wanted_key2] => 5
            [wanted_key3] => 6
        )
)
  

Песочница

Для ясности все, что вам нужно, это это, остальное для тестирования:

 $map = array_flip(['wanted_key1', 'wanted_key2', 'wanted_key3']);
$res = array_map(function($item)use($map){return array_intersect_key((array)$item,$map);},$array);
  

Комментарии:

1. извините за поздний ответ, но спасибо! Это именно то, чего я хотел 🙂

Ответ №2:

array_filter() должен выполнить работу.

Простой пример:

 $original = ['a' => 2, 'b' => 5, 'c' => 6];

$filtered = array_filter($original, function($item) {
    // This anonymous function must return true for keeping your item, or false for not keeping it

    // There I want to keep items with a value more than 4.
    return ($item > 4);
});

// Output of $filtered: ['b' => 5, 'c' => 6]
  

Тот же пример с массивом объектов, предположив, что они обладают value свойством:

 $filtered = array_filter($original, function($item) {
    // There I want to keep items with a value more than 4.
    return ($item->value > 4);
});

// Output of $filtered: ['b' => 5, 'c' => 6]
  

Если ваша логика заключается в фильтрации по ключам, третий параметр flag должен быть установлен на ARRAY_FILTER_USE_KEY . Тогда $item это будут ваши ключи, а не значения.

Комментарии:

1. ключи, которые я хочу сохранить, одинаковы во всех объектах, но «значения» для всех них разные и не обязательно числовые. Я хочу сохранить wanted_key1, 2 и 3 и связанное с ними другое «значение»

Ответ №3:

Аналогично ответу ArtisticPheonix, перебираем и сохраняем нужные ключи, используя пересечение:

 <?php

$data =
[
    ['fruit'=>'apple',  'veg'=>'carrot'],
    ['fruit'=>'banana', 'veg'=>'marrow']
];

$flipped_wanted_keys = array_flip(['fruit']);
foreach($data as amp;$item)
    $item = array_intersect_key($item, $flipped_wanted_keys);

unset($item);
print_r($data);
  

Вывод:

 Array
(
    [0] => Array
        (
            [fruit] => apple
        )

    [1] => Array
        (
            [fruit] => banana
        )

)
  

Поскольку у вас есть объекты в вашем массиве, удаление свойств требует другого подхода, но если вы довольны тем, что на выходе у вас многомерный массив, как указано выше, тогда вам просто нужно преобразовать ваш объект в массив перед пересечением ключей (при условии, что это доступные свойства).

 $item = array_intersect_key((array) $item, $flipped_wanted_keys);