javascript - 按属性嵌套/分组对象数组,忽略 null/undefined 并使用附加属性作为标签

标签 javascript lodash

我正在尝试对一组对象进行嵌套分组。

这个要点提供的功能几乎按预期工作,并使用 lodash 作为基础:

https://gist.github.com/joyrexus/9837596

const _ = require('lodash');

function nest(seq, keys) {
    if (!keys.length) return seq;
    let [first, ...rest] = keys;
    return _.mapValues(_.groupBy(seq, first), value => nest(value, rest));
}

这是递归的,

但是,我面临两个问题。

  1. 如果一个参数设置为nullundefined,它被用作一个组,而不是
  2. 一个可选的对象属性应该被用作最终的对象键,所以只有对象,没有数组。此属性始终必须是唯一的才能正常工作。

是否可以结合或扩展现有的nest功能来解决以上几点?

这种方法的优点是,除了键,我还可以使用函数数组 (p => p.parameterGroup1) 来返回参数。因此,除了最后一个可选参数,我还可以使用 p => p.parameterGroup1 吗? p.parameterGroup1 : p.label

我准备了一个小测试,让你更好地了解预期的结果:

test('nest array of objects by groups as keys, stopping at null and using a final label param', t => {
    let properties = [
        {
            parameterGroup1: 'first',
            parameterGroup2: 'second',
            parameterGroup3: 'third',
            label: 'A'
        },
        {
            parameterGroup1: 'first',
            parameterGroup2: 'second',
            parameterGroup3: null,
            label: 'B'
        },
        {
            parameterGroup1: 'a',
            parameterGroup2: 'b',
            parameterGroup3: undefined,
            label: 'C'
        },
    ]
    let expected = {
        first: {
            second: {
                third: {
                    A: {
                        parameterGroup1: 'first',
                        parameterGroup2: 'second',
                        parameterGroup3: 'third',
                        label: 'A'
                    }
                },
                B: {
                    parameterGroup1: 'first',
                    parameterGroup2: 'second',
                    parameterGroup3: null,
                    label: 'B'
                }
            }
        },
        a: {
            b: {
                C: {
                    parameterGroup1: 'a',
                    parameterGroup2: 'b',
                    parameterGroup3: undefined,
                    label: 'C'
                }
            }
        }
    }
    let grouped = nest(properties, ['parameterGroup1', 'parameterGroup2', 'parameterGroup3'], 'label')
    t.deepEqual(grouped, expected)
})

提前致谢!

最佳答案

这是在 vanilla js 中实现的一种方法。我们通过reduce数组seq构造result对象:对于数组中的每个对象obj seq,我们使用来自 keys 的键的 obj 的值逐层遍历 result 对象。如果该值为 nullundefined,我们将跳过(不会再往下一层)。如果该值存在,我们将下降一个级别,如果它尚不存在,则创建一个级别(对象)。我们在 keys 数组上使用 reduce 重复执行此操作,直到找到叶对象(最后一级),我们将当前对象分配给评估 获得的键>obj[最后一个]:

function nest(seq, keys, last) {
    return seq.reduce((result, obj) => {
        // First we find the (last level) object to which we will assign our current object to, as a child
        let lastLevel = keys.reduce((res, key) => {               // for each key in keys
            let value = obj[key];                                 // get the value from our current object obj for that key key
            if(value == null) return res;                         // if the value is null or undefined, skip
            if(res[value]) return res[value];                     // if the level for value exists return it
            return res[value] = {};                               // if it doesn't, create a new level, assing it to result and return it
        }, result);

        // then we assign it using the value of the key last
        lastLevel[obj[last]] = obj;                               // we found the last possible level, assign obj to it under the key obj[last]

        return result;
    }, {});
}

示例:

function nest(seq, keys, last) {
    return seq.reduce((result, obj) => {
        let lastLevel = keys.reduce((res, key) => {
            let value = obj[key];
            if(!value) return res;
            if(res[value]) return res[value];
            return res[value] = {};
        }, result);
        lastLevel[obj[last]] = obj;
        return result;
    }, {});
}



let properties = [{parameterGroup1: 'first',parameterGroup2: 'second',parameterGroup3: 'third',label: 'A'},{parameterGroup1: 'first',parameterGroup2: 'second',parameterGroup3: null,label: 'B'},{parameterGroup1: 'a',parameterGroup2: 'b',parameterGroup3: undefined,label: 'C'}];

let grouped = nest(properties, ['parameterGroup1', 'parameterGroup2', 'parameterGroup3'], 'label');
console.log(grouped);

关于javascript - 按属性嵌套/分组对象数组,忽略 null/undefined 并使用附加属性作为标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50213743/

相关文章:

javascript - 如何使用 AngularJS 将数组转换为字符串 url?

javascript - 如何使用Lodash让这个映射变得更简单?

javascript - 比较两个数组并分组为插入和更新

javascript - 动态更改所有 <img> 标签的样式

javascript - 使用嵌套数组中的值对 json 对象进行分组求和和转换

object - Lodash _.omit 函数在 map 内

javascript - querySelectorAll 和 getElementsBy* 方法返回什么?

javascript - 抽屉不适用于 `mdl-layout--fixed-header` 类

javascript - 如何使用 loadash/javascript 嵌套多个 groupby

javascript - 如何获取对象数组的某些部分作为新数组?