Laravel集合 - 列出多个值

时间:2016-03-11 19:51:24

标签: laravel collections laravel-5.2

我正在寻找一个集合并返回包含集合中两个字段的平面数组。我想要的是什么:

$collection = new Collection([
    [
        "a"=>"a1",
        "b"=>"b1",
        "c"=>"c1"
    ],
    [
        "a"=>"a2",
        "b"=>"b2",
        "c"=>"c2"
    ],
    [
        "a"=>"a3",
        "b"=>"b3",
        "c"=>"c3"
    ]
]);

//desired output:
[
    ["a1","b1"],
    ["a2","b2"],
    ["a3","b3"]
];

我会认为这是一个功能,但它不是:

$collection->lists(["a","b"]);

我目前的解决方案看起来效率不高,因为它们可能有数千行:

$collection->lists("a")->zip($collection->lists("b"));

我是否缺少某项功能?感谢。

编辑:我也使用了这样的地图:

$collection->map(function($row)){
    return [$row['a'],$row['b']];
}

这似乎比我想要的更加习惯。如果没有本地方式,我最终可能会使用此函数为Collection编写包装器。

4 个答案:

答案 0 :(得分:9)

如果您想专门使用集合,可以扩展当前集合API,因为它是可宏的,执行如下操作:

Collection::macro('pluckMultiple', function ($assoc) {
    return $this->map(function ($item) use ($assoc) {
        $list = [];
        foreach ($assoc as $key) {
            $list[$key] = data_get($item, $key);
        }
        return $list;
    }, new static);
});

在上面的示例中,我将键作为返回的一部分包含在内,但可以删除它。

$collection->pluckMultiple(['a', 'b']);

会给你你想要的东西。

如果您想从Eloquent集合中提取项目,上述方法可以很好地工作,例如:

$books = Book::with('author')->get();
$books->pluckMultiple(['title', 'author.name', 'author.surname']);

答案 1 :(得分:5)

您可以使用

$plucked = $collection->pluck('b','a');

$plucked->all();

这将给出以下结果

Collection {#651 ▼
#items: array:3 [▼
"a1" => "b1"
"a2" => "b2"
"a3" => "b3"
]}

并使用此代码获取给定格式

foreach ($plucked as $key => $item)
{
 $temp[] = [ $key, $item];
}

这将产生以下结果。

array:3 [▼
 0 => array:2 [▼
  0 => "a1"
  1 => "b1"
  ]
 1 => array:2 [▼
  0 => "a2"
  1 => "b2"
  ]
 2 => array:2 [▼
  0 => "a3"
  1 => "b3"
 ]
]

答案 2 :(得分:0)

如果您使用Laravel 5.0,您会发现Illuminate\Laravel\Collection不接受宏,因此Leon的优雅解决方案无效。如果(像我一样)你无法升级到更新的Laravel版本,你可以使用此功能作为解决方法:

<?php

use Illuminate\Support\Collection;

/**
 * List values from collection. Unlike $collection->lists('key'), this function allows using multiple keys.
 *
 * In newer Laravel versions things like that can be done with collection macros, but not in 5.0.
 *
 * @param Collection $collection
 * @param array|string $properties
 * @param string $id
 * @return array
 */
function lists(Collection $collection, $properties, $id = null) {
    $result = [];
    $i = 0;

    foreach ($collection as $item) {
        $k = $id ? $item->$id : $i;
        if (is_array($properties)) {
            $result[$k] = [];
            foreach ($properties as $property) {
                $result[$k][$property] = $item->$property;
            }
        }
        else {
            $result[$k] = $item->$properties;
        }
        $i++;
    }

    return $result;
}

然后你就像这样使用它:

$users = User::all();
$someData = lists($collection, ['name', 'email']);
// Or, if you want to key by id:
$someData = lists($collection, ['name', 'email'], 'id');

至于你把这个功能放在哪里 - 我把这样的东西放在app / Support / helpers.php中,然后像这样更新我的composer.json:

"autoload": {
    ...
    "files": [
        "app/Support/helpers.php"
    ]
},

然后运行composer dump

答案 3 :(得分:-1)

我修改了Leon Vismer的答案,在数组中使用点符号。

        Collection::macro('pluckMultiple', function ($assoc) {
        /* @var $this Collection */
        return $this->map(function ($item) use ($assoc) {
            $list = [];
            foreach ($assoc as $keys) {
                $old_key = $keys;
                $keys    = explode('.', $keys);
                $ref     = &$list;

                while (count($keys) > 1) {
                    $key = array_shift($keys);
                    if (!isset($ref[ $key ]) || !is_array($ref[ $key ])) {
                        $ref[ $key ] = [];
                    }

                    $ref = &$list[ $key ];
                }

                $ref[ array_shift($keys) ] = data_get($item, $old_key);
            }

            return $list;
        }, new static);
    });