PHP — Фильтровать объекты на основе значений массива внутри каждого объекта

#php

#php

Вопрос:

У меня есть массив объектов, где каждый объект содержит массив для атрибута

 $cars = [
    "toyota" => ["colors" => ["red","blue"]],
    "mazda" => ["colors" => ["red"]],
    "honda" => ["colors" => ["blue"]],
    "nissan" => ["colors" => ["red","yellow"]],
];
  

Мне нужна функция, которая вернет все автомобили, имеющие указанный цвет.

Я могу сделать это, используя цикл foreach.

 function getCarsByColor(string $color, array $cars){
    foreach($cars as $key => $car){
        if(!in_array($color, $car['colors'])){
          unset($cars[$key]);
        }
    }

    return $cars;
}
  

Просто интересно, есть ли более прямой способ сделать это.

Спасибо.

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

1. Вы получаете данные из mysql? Если это так, вы могли бы сделать это в своем запросе

2. Это хороший момент. На самом деле это Postgres. Объект cars хранится внутри другого объекта, как jsonb, так как бы отфильтровать это при запросе к нему?

3. что-то вроде Select car.name, color.name from car inner join color on color.idCar = car.id where color = 'yourColorByPreparedStatementHere'

4. Я не думаю, что смогу выполнить этот запрос в jsonb. Если бы атрибуты car хранились в их столбцах, то это сработало бы

Ответ №1:

Этот подход использует array_filter()

 $red_cars = array_filter($cars, function($car) {
    return in_array('red', $car['colors']);
});
  

Как функция

 function get_cars_by_color(array $cars, string $color = '') {
    return array_filter($cars, function($car) use ($color) {
        return in_array($color, $car['colors']);
    });

}
  

use() передает переменную из текущей области в область функций закрытия.

Ответ №2:

В том, что вы делаете, нет ничего концептуально неправильного. В этом конкретном сценарии на самом деле у вас есть только два варианта: 1) изменить копию массива, чтобы удалить ненужные записи (что вы делаете сейчас), или 2) создать новый массив с только желаемыми записями. Выбирайте сами, на самом деле. Одна вещь, которую я замечаю:

 if(!in_array($color, $car['color'])){
  

Возможно, это опечатка, но на основе вашего определения массива не будет индекса с именем ‘color’.