【问题标题】:Laravel collections: Flatten with full key nameLaravel 集合:用全键名展平
【发布时间】:2017-10-08 19:02:02
【问题描述】:

Laravel Collections 有没有办法用键“命名空间”来展平数组。类似的东西:

$a = collect([
    'id' => 1,
    'data' => [
        'a' => 2,
        'b' => 3
    ]
]);

$a = $a->flattenWithKeysNamespace(); // <-- this does not exists

// Should returns: 
// ['a' => 1, 'data.b' => 2, 'data.c' => 3]; // <-- I would like this.

我知道我可以在原始 PHP 中或使用一些 Collection 函数组合来做到这一点,但有时我会错过 Laravel Collection 文档中的某些内容。那么 Collection 函数有没有一种简单的方法来做到这一点?

【问题讨论】:

  • 我认为你是对的,因为没有“Laravel 方式”可以做到这一点。如果您愿意将Collection 转换为数组,则this 之类的答案显示了一种在 PHP 中执行此操作的方法,但是由于您提到原始 PHP,我假设您已经找到了这种解决方案。我认为使用Collection 方法最好的办法是编写与我链接的函数类似的函数,但使用flatMap() 之类的函数,并在您的元素也是一个集合时递归调用您的函数。
  • 谢谢!您可以发表您的评论作为答案,我会接受!

标签: laravel laravel-5 laravel-5.4 laravel-collection


【解决方案1】:

如果您不关心转换的深度级别,我认为对您来说最简单的选择就是 array_dot 辅助函数。如果您想更精细地控制递归的深度,以及是否有点分隔的数组键,我已经编写了一个可以做到这一点的集合宏。通常collect($array)-&gt;collapse() 维护字符串键,但非增量数字键仍然会丢失,即使强制键入字符串也是如此。而且我最近需要维护它们。

把它放在你的AppServiceProvider::boot() 方法中:

    /**
     * Flatten an array while keeping it's keys, even non-incremental numeric ones, in tact.
     *
     * Unless $dotNotification is set to true, if nested keys are the same as any
     * parent ones, the nested ones will supersede them.
     *
     * @param int $depth How many levels deep to flatten the array
     * @param bool $dotNotation Maintain all parent keys in dot notation
     */
    Collection::macro('flattenKeepKeys', function ($depth = 1, $dotNotation = false) {
        if ($depth) {
            $newArray = [];
            foreach ($this->items as $parentKey => $value) {
                if (is_array($value)) {
                    $valueKeys = array_keys($value);
                    foreach ($valueKeys as $key) {
                        $subValue = $value[$key];
                        $newKey = $key;
                        if ($dotNotation) {
                            $newKey = "$parentKey.$key";
                            if ($dotNotation !== true) {
                                $newKey = "$dotNotation.$newKey";
                            }

                            if (is_array($value[$key])) {
                                $subValue = collect($value[$key])->flattenKeepKeys($depth - 1, $newKey)->toArray();
                            }
                        }
                        $newArray[$newKey] = $subValue;
                    }
                } else {
                    $newArray[$parentKey] = $value;
                }
            }

            $this->items = collect($newArray)->flattenKeepKeys(--$depth, $dotNotation)->toArray();
        }

        return collect($this->items);
    });

然后您可以致电collect($a)-&gt;flattenKeepKeys(1, true); 并取回您所期望的。

【讨论】:

    【解决方案2】:

    我认为你是对的,没有“Laravel 方式”可以做到这一点。如果您愿意将Collection 转换为数组,则this 之类的答案显示了一种在 PHP 中执行此操作的方法,但是由于您提到原始 PHP,我假设您已经找到了这种解决方案。

    我认为使用Collection 方法最好的办法是编写与我链接的函数类似的函数,但使用flatMap() 之类的函数,并在元素也是集合时递归调用函数。

    【讨论】:

    • 这可能会晚,但以防万一有人需要,请查看Arr::dot()
    猜你喜欢
    • 2017-07-22
    • 2018-05-25
    • 2020-05-07
    • 2021-06-11
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    相关资源
    最近更新 更多