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

时间:2018-08-23 15:27:11

标签: javascript lodash

这是我的对象数组

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

结果应该是这样

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

因此,我想摆脱属性key3中的子数组,并获得新的等效结构,并复制所有其他属性。

出于无法更改的原因,我应该使用lodash,但只能在2.4.2版中使用

编辑:详细说明:我使用的是基于JSON的表单引擎,该引擎允许使用现有功能(例如lodash函数),但不允许定义新功能。我也不能使用for循环之类的控制结构。本质上,我只能使用链式基本函数调用,包括lodash。

我尝试使用map,但是map无法扩展数组,它只能将一个数组元素转换为其他内容

我可以在这里使用任何破破烂烂的魔术吗?

EDIT2:这是一个有关我说“我不能引入新功能”时的意思的示例。它将检查某个属性子集的对象数组是否唯一

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 个答案:

答案 0 :(得分:1)

嗯,这是一个挑战!我有一个可行的解决方案,涵盖了我能想到的所有情况,但是如果我错过了情况,请告诉我。


我的一般方法是从头开始的,我知道我将使用_.zipObject创建结果对象。从那里开始,只需要使其他属性与必要的key3值对齐即可。为此,我只需复制属性值,使key3的每个值都有其自己的副本。接下来,我将它们链接起来并创建对象。最后,我过滤掉所有不必要的对象副本。

注意:此方法不适用于undefined中的key3元素。我认为这是一种不太可能的情况,因此没有尝试解决。


可理解的版本:

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");

性能:

我希望它对于大的初始数组或大长度的key3来说是可怕的。我特别对单行版本感到不寒而栗。如果有人抱怨,我会指出这是由于执行环境的限制所致。


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

答案 1 :(得分:0)

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)

答案 2 :(得分:-1)

这是使用香草JS的解决方案

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);

如果您要使用lodash,我想等效的是:

const _ = require('lodash')
const result = _.reduce(array, (final, item) => {
    _.forEach(item.key3, (key3Val) => {
        final.push(Object.assign({}, item, {
            "key3": key3Val
        }))
    })
    return final;
}, []);

答案 3 :(得分:-1)

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>

相关问题