代码之家  ›  专栏  ›  技术社区  ›  devnull69

如何在对象数组中“展开”子数组

  •  5
  • devnull69  · 技术社区  · 6 年前

    [{
        "key1": "value1",
        "key2": "value2",
        "key3": ["value3", "value4"]
    }]
    

    结果应该是这样

    [{
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }, {
        "key1": "value1",
        "key2": "value2",
        "key3": "value4"
    }]
    

    所以我想去掉属性中的子数组 key3 并得到新的等价结构,复制所有其他属性。

    编辑:更详细地说:我使用的是一个基于JSON的表单引擎,它允许使用现有的函数(比如lodash函数),但不允许定义新的函数。我也不能像for循环那样使用控制结构。实际上,我只能使用链式基本函数调用,包括lodash。

    我试图使用map,但是map不能扩展数组,它只能将一个数组元素转换成不同的元素

    我能在这里使用什么魔法吗?

    model = [{
        "key1": "value1",
        "key2": "value2",
        "key3": "valuex"
    },{
        "key1": "value1",
        "key2": "value2",
        "key3": "valuey"
    }]
    
    // will give false because the two objects are not unique regarding the combination of "key1" and "key2"
    _.uniq(model.map(_.partialRight(_.pick, ["key1", "key2"])).map(JSON.stringify)).length === model.length
    
    4 回复  |  直到 6 年前
        1
  •  1
  •   Vlad274    6 年前

    好吧,这是个挑战!我有一个工作解决方案,涵盖所有我能想到的情况,但请让我知道,如果有我错过的情况。


    我的基本方法从最后开始,我知道我会用 _.zipObject 创建结果对象。从那里开始,这只是一个让其他物业与必要的 key3 键3 有自己的副本。接下来,我将它们链接起来并创建对象。最后,我过滤掉所有不必要的对象副本。

    undefined 元素 . 我认为这是一个不太可能的情况,因此没有试图解决。


    可理解的版本:

    const objects = [{
        "key1": "value1",
        "key2": "value2",
        "key3": ["value3", "value4"]
    },
    {
        "key1": "value5",
        "key2": "value6",
        "key3": ["value7"]
    }];
    
    // Get other key names
    const otherKeys = _.without(_.keys(objects[0]), "key3");
    // Get values without key3
    const otherValues = _.map(_.map(objects, _.partialRight(_.omit, "key3")), _.values);
    // Get just key3 values
    const onlyKey3 = _.map(objects, "key3");
    
    // Generate dummy range of needed length
    const maxLengthKey3 = _.max(_.map(onlyKey3, "length"));
    const dummyRange = _.range(maxLengthKey3);
    
    // Grow all arrays to needed length
    const newOtherValues = _.flatten(_.map(dummyRange, _.partial(_.identity, otherValues)), true);
    const newKey3 = _.flatten(_.map(dummyRange, _.partial(_.map, onlyKey3)));
    
    const pairedValues = _.map(_.zip(newOtherValues, newKey3), _.flatten);
    const resultObjects = _.map(pairedValues, _.partial(_.zipObject, _.union(otherKeys, ["key3"])));
    
    // Filter out unnecessary objects
    const result = _.filter(resultObjects, "key3");
    

    一字排开:

    const objects = [{
        "key1": "value1",
        "key2": "value2",
        "key3": ["value3", "value4"]
    },
    {
        "key1": "value5",
        "key2": "value6",
        "key3": ["value7"]
    }];
    // One line
    const result = _.filter(_.map(_.map(_.zip(_.flatten(_.map(_.range(_.max(_.map(_.map(objects, "key3"), "length"))), _.partial(_.identity, _.map(_.map(objects, _.partialRight(_.omit, "key3")), _.values))), true), _.flatten(_.map(_.range(_.max(_.map(_.map(objects, "key3"), "length"))), _.partial(_.map, _.map(objects, "key3"))))), _.flatten), _.partial(_.zipObject, _.union(_.without(_.keys(objects[0]), "key3"), ["key3"]))), "key3");
    

    性能:

    我认为对于一个大的初始数组或者一个大的长度 键3 . 对于单行版本我特别不寒而栗。如果有人抱怨,我会指出这是由于执行环境的限制造成的。


    在浏览器中通过 https://npm.runkit.com/lodash ,使用 var _ = require('lodash@2.4.2');

        2
  •  0
  •   Francis Leigh    6 年前

    let obj = {
        key1: "value1",
        key2: "value2",
        key3: ["value3", "value4"]
    }
    
    let tracker = new Array(obj.key3.length)
    
    let newObjArr = []
    
    for (let i = 0; i < tracker.length; i++) {
      newObjArr.push({
        key1: obj.key1,
        key2: obj.key2,
        key3: obj.key3[i]
      })
    }
    
    console.log(newObjArr)
        3
  •  -1
  •   Ayush Gupta    6 年前

    let array = [{
        "key1": "value1",
        "key2": "value2",
        "key3": ["value3", "value4"]
    }, {
        "key1": "value5",
        "key2": "value6",
        "key3": ["value7", "value8"]
    }, ]
    
    const result = array.reduce((final, item) => {
        for (let i = 0; i < item.key3.length; i++) {
            final.push(Object.assign({}, item, {
                "key3": item.key3[i]
            }))
        }
        return final;
    }, []);
    
    console.log(result);

    如果你用洛达斯,我想相当于:

    const _ = require('lodash')
    const result = _.reduce(array, (final, item) => {
        _.forEach(item.key3, (key3Val) => {
            final.push(Object.assign({}, item, {
                "key3": key3Val
            }))
        })
        return final;
    }, []);
    
        4
  •  -1
  •   Karan    6 年前

    var model = [{
      "key1": "value1",
      "key2": "value2",
      "key3": ["value3", "value4"]
    }];
    
    model = _.flatten(_.forEach(model, function(x) {
      _.forEach(x.key3, function(y, i) {
        x.key3[i] = {
          "key1": x["key1"],
          "key2": x["key2"],
          "key3": y
        }
      });
    }), "key3");
    
    console.log(model);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.2/lodash.min.js"></script>