PHP - получить несколько столбцов из массива - PullRequest
0 голосов
/ 08 октября 2018

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

0 => array:3 [
    "product_id" => "1138"
    "product_image" => "/resources/medias/shop/products/shop-6500720--1.png"
    "product_sku" => "6500722"
  ]
1 => array:3 [
    "product_id" => "1144"
    "product_image" => "/resources/medias/shop/products/shop-6501041--1.png"
    "product_sku" => "6501046"
  ]
2 => array:3 [
    "product_id" => "113"
    "product_image" => "/resources/medias/shop/products/shop-6294909--1.png"
    "product_sku" => "6294915"
]

Мне нужен способ получить множественный массив только с необходимыми столбцами (array_column не вариант, так как он дает мне только 1 столбец).

Что я сделал

function colsFromArray($array, $keys)
{
    return array_map(function ($el) use ($keys) {
        return array_map(function ($c) use ($el) {
            return $el[$c];
        }, $keys);
    }, $array);
}

$array = array(
    [
        "product_id"    => "1138",
        "product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
        "product_sku"   => "6500722"
    ],
    [
        "product_id"    => "1144",
        "product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
        "product_sku"   => "6501046"
    ],
    [
        "product_id"    => "113",
        "product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
        "product_sku"   => "6294915"
    ]
);
colsFromArray($array, array("product_id", "product_sku"));

//0 => array:3 [
//    "product_id" => "1138"
//    "product_sku" => "6500722"
//  ]
//1 => array:3 [
//    "product_id" => "1144"
//    "product_sku" => "6501046"
//  ]
//2 => array:3 [
//    "product_id" => "113"
//    "product_sku" => "6294915"
//]

Проблема в том, что он выглядит слишком медленным , поскольку он повторяется дважды.Есть ли способ получить несколько столбцов без этого обходного пути?PHP: 5,6

Ответы [ 5 ]

0 голосов
/ 27 июня 2019

Я преобразовал элегантный подход из @Chayan в функцию, чтобы его можно было использовать как array_column().Отфильтрованные ключи теперь могут быть представлены в виде простого массива.

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

<?php

function array_columns(array $arr, array $keysSelect)
{    
    $keys = array_flip($keysSelect);
    $filteredArray = array_map(function($a) use($keys){
        return array_intersect_key($a,$keys);
    }, $arr);

    return $filteredArray;
}

$arr = array(
    [
        "product_id"    => "1138",
        "product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
        "product_sku"   => "6500722"
    ],
    [
        "product_id"    => "1144",
        "product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
        "product_sku"   => "6501046"
    ],
    [
        "product_id"    => "113",
        "product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
        "product_sku"   => "6294915"
    ]
);

$keysSelect = array("product_id" , "product_sku");
$filteredArray = array_colums($arr, $keysSelect);

var_dump($filteredArray);
0 голосов
/ 08 октября 2018

Если вы не хотите изменять исходный массив и хотите получить желаемый вывод

Используйте функцию array_insersect_key , чтобы получить желаемый вывод в следующем виде

$array = array(
    [
        "product_id"    => "1138",
        "product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
        "product_sku"   => "6500722"
    ],
    [
        "product_id"    => "1144",
        "product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
        "product_sku"   => "6501046"
    ],
    [
        "product_id"    => "113",
        "product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
        "product_sku"   => "6294915"
    ]
);

$keys = array("product_id"=>1, "product_sku"=>2);

$filteredArray = array_map(function($a) use($keys){
    return array_intersect_key($a,$keys);
}, $array);

print_r($filteredArray);
0 голосов
/ 08 октября 2018

Если вам нужны два столбца из массива, один из которых является SKU (который обычно является уникальным), тогда вы можете использовать array_column с третьим параметром.

$new = array_column($arr, "product_id", "product_sku");

Это вернет плоский массив с SKU какключ и ID в качестве значения, облегчающего работу с массивом.

Вывод:

array(3) {
  [6500722]=>
  string(4) "1138"
  [6501046]=>
  string(4) "1144"
  [6294915]=>
  string(3) "113"
}

https://3v4l.org/UDGiO

0 голосов
/ 08 октября 2018

Я думаю, что большая проблема в том, что вы теряете ключи

Оригинальный код

array (
  0 => 
  array (
    0 => '1138',
    1 => '6500722',
  ),
  1 => 
  array (
    0 => '1144',
    1 => '6501046',
  ),
  2 => 
  array (
    0 => '113',
    1 => '6294915',
 );

Вы можете использовать простой foreach вместо второй карты array_map:

function colsFromArray(array $array, $keys)
{
    if (!is_array($keys)) $keys = [$keys];
    return array_map(function ($el) use ($keys) {
        $o = [];
        foreach($keys as $key){
            //  if(isset($el[$key]))$o[$key] = $el[$key]; //you can do it this way if you don't want to set a default for missing keys.
            $o[$key] = isset($el[$key])?$el[$key]:false;
        }
        return $o;
    }, $array);
}

Вывод

array (
  0 => 
  array (
    'product_id' => '1138',
    'product_sku' => '6500722',
  ),
  1 => 
  array (
    'product_id' => '1144',
    'product_sku' => '6501046',
  ),
  2 => 
  array (
    'product_id' => '113',
    'product_sku' => '6294915',
  ),
)

Песочница

проблема в том, что она кажется слишком запаздывающей, так как она повторяется дважды по этому.

Нет реального способа не повторять его 2 раза, но вы, вероятно, тоже не хотите выбрасывать ключи.

При этом вы можете рекурсивно сбросить элементы, которые выне хочу.

function colsFromArray(array &$array, $keys)
{
    if (!is_array($keys)) $keys = [$keys];
    foreach ($array as $key => &$value) {
        if (is_array($value)) {
            colsFromArray($value, $keys); //recursive
        }else if(!in_array($key, $keys)){
           unset($array[$key]); 
        }
    }
}

colsFromArray($array, array("product_id", "product_sku"));
var_export($array);

Тот же вывод, что и раньше

Это проще сделать по ссылке.Скорее, быстрее, вам придется проверить 2 и посмотреть.

Песочница

В качестве последнего замечания вы не должны предполагать, что ключ будет существовать илиэти ключи будут массивом, если вы не введете его как массив.

Вы также можете сделать это с фильтром массива

function colsFromArray(array $array, $keys)
{
    if (!is_array($keys)) $keys = [$keys];
    $filter = function($k) use ($keys){
       return in_array($k,$keys);
    };
    return array_map(function ($el) use ($keys,$filter) {
        return array_filter($el, $filter, ARRAY_FILTER_USE_KEY );
    }, $array);
}

Существует небольшое преимущество в производительности для объявления функции фильтрациивне цикла (array_map).

Песочница

0 голосов
/ 08 октября 2018

Если я правильно понимаю ваш вопрос, вы можете попробовать традиционный foreach - он может быть немного быстрее.

function colsFromArray($array, $filterKeys) {
    $newArr = [];
    foreach($array as $key => $val) {
       $element = [];
       foreach($filterKeys as $filterKey) {
          $element[$filterKey] = $val[$filterKey];
       }
       $newArr[] = $element;
    }
}

(не проверено)

Проблема в том, чтоон кажется слишком запаздывающим, поскольку он повторяется дважды по этому

Ваш исходный код не повторяется дважды по одному и тому же массиву.Вы не сможете обойти итерации по основному массиву, а затем по массиву filterKeys, если хотите иметь массив, в котором каждый элемент представляет собой другой массив элементов с ключами из массива filterKeys.

...