简体   繁体   English

合并JavaScript中的嵌套对象数组

[英]Merge nested array of objects in JavaScript

I have an array of objects with a nested array of objects like: 我有一个带有嵌套对象数组的对象数组:

var cars = [
  {
    Plate: '112211',
    Details:
      [
        {
          Desc: 'Blah11 Blah Blah',
        Miles: '111',
        Color: 'blue'
        },
        {
          Desc: 'Blah B22lah Blah',
        Miles: '222',
        Color: 'green'
        },
      ],
      Make:'Honda'
  },
      Plate: '223322',
    Details:
      [
        {
          Desc: 'Blah Blah B33lah',
        Miles: '333',
        Color: 'yellow'
        },
        {
          Desc: 'Blah B44lah Blah',
        Miles: '444',
        Color: 'red'
        }
      ],
      Make:'GMC'
  },
      Plate: '334433',
    Details:
      [
        {
          Desc: 'Bl55ah Blah Blah',
        Miles: '555',
        Color: 'blue'
        },
        {
          Desc: 'Blah B66lah Blah',
        Miles: '666',
        Color: 'pink'
        },
      ],
      Make:'Ford'
  }
]

I am trying to find a way to turn it into a new array that flattens or merges the nested array. 我正在尝试找到一种方法来将其转换为可以使嵌套数组变平或合并的新数组。 The goal would be to have something like: 目标是拥有类似的东西:

[
  {
    Plate: '112211',
    Desc: 'Blah11 Blah Blah',
    Miles: '111',
    Color: 'blue',
    Make:'Honda'
  },
  {
    Plate: '112211',
    Desc: 'Blah B22lah Blah',
    Miles: '222',
    Color: 'green',
    Make: 'Honda'
    },
    {
    Plate: '223322',
    Desc: 'Blah Blah B333lah',
    Miles: '333',
    Color: 'yellow'
    Make: 'GMC'
    },
    {
    Plate: '223322',
    Desc: 'Blah Bl444ah B33lah',
    Miles: '444',
    Color: 'red',
    Make: 'GMC'
    },
    {
    Plate: '334433',
    Desc: 'Bl555ah Blah B33lah',
    Miles: '555',
    Color: 'blue',
    Make: 'Ford'
    },
    {
    Plate: '334433',
    Desc: 'Blah Bl666ah B33lah',
    Miles: '666',
    Color: 'pink',
    Make: 'Ford'
    },
]

lodash _.flatten and _.flattenDeep didn't do anything. lodash _.flatten和_.flattenDeep没有执行任何操作。 I have also tried doing a _.chain and flatten to build a new array, but that come up empty 我也曾尝试做一个_.chain并展平以建立一个新的数组,但是结果是空的

var actions = _.chain(cars).flatten("Details");

        for (i = 0; i < cars.length; i++) {
            actions.each(function(action) {
                list.push(cars[i].Plate);
                list.push(action);
                list.push(cars[i].Make);

Here is the code 这是代码

 function merge(collection) { return _(collection).map(function(obj) { return _(obj) .pickBy(_.isArray) .values() .flatten() .map(function(dest) { return _.merge(dest, _.omitBy(obj, _.isArray)); }) .value(); }) .flatten() .value(); } var cars = [{ Plate: '112211', Details: [{ Desc: 'Blah11 Blah Blah', Miles: '111', Color: 'blue' }, { Desc: 'Blah B22lah Blah', Miles: '222', Color: 'green' }], Make: 'Honda' }, { Plate: '223322', Details: [{ Desc: 'Blah Blah B33lah', Miles: '333', Color: 'yellow' }, { Desc: 'Blah B44lah Blah', Miles: '444', Color: 'red' }], Make: 'GMC' }, { Plate: '334433', Details: [{ Desc: 'Bl55ah Blah Blah', Miles: '555', Color: 'blue' }, { Desc: 'Blah B66lah Blah', Miles: '666', Color: 'pink' }], Make: 'Ford' }]; var result = merge(cars); document.querySelector('#result').innerHTML = JSON.stringify(result, null, 2); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.5.1/lodash.min.js"></script> <pre id="result"></pre> 

There may be a better way to do this, but this gets the job done: 也许有更好的方法可以做到这一点,但这可以完成工作:

 var cars = [ { Plate: '112211', Details: [ { Desc: 'Blah11 Blah Blah', Miles: '111', Color: 'blue' }, { Desc: 'Blah B22lah Blah', Miles: '222', Color: 'green' }, ], Make:'Honda' }, { Plate: '223322', Details: [ { Desc: 'Blah Blah B33lah', Miles: '333', Color: 'yellow' }, { Desc: 'Blah B44lah Blah', Miles: '444', Color: 'red' } ], Make:'GMC' }, { Plate: '334433', Details: [ { Desc: 'Bl55ah Blah Blah', Miles: '555', Color: 'blue' }, { Desc: 'Blah B66lah Blah', Miles: '666', Color: 'pink' }, ], Make:'Ford' } ]; var details = []; _.each(cars, function(car) { var keys = _.keys(car); _.each(car.Details, function(dtl) { _.each(keys, function(key) { if (key !== 'Details') { dtl[key] = car[key]; } }); details.push(dtl); }); }); console.log(details); document.querySelector('#details').innerHTML = JSON.stringify(details); document.querySelector('#numDetails').innerHTML = details.length; 
 <script src="https://cdn.rawgit.com/lodash/lodash/3.0.1/lodash.min.js"></script> <div id="numDetails"></div> <div id="details"></div> 

I am sure there's a cleaner way (using _.filter or some such) to remove 'Details' from the keys, but it's sleepy where I am ;). 我确信有一种更干净的方法(使用_.filter或类似的方法)从键中删除“ Details”,但是我在这里很困;)。

If flattening won't work, you can just reduce. 如果展平不起作用,则可以减小。 Here I construct each of the cars given using the params in details so they can remain monomorphic while they're being flattened and beyond, if you choose. 在这里,我详细地使用参数构造了给定的每辆汽车,以便它们在展平时可以保持单态性,如果您选择的话,也可以保持不变。

Ideally the way you have your state set up shouldn't have to have separate keys under the details one. 理想情况下,状态设置的方式不必在详细信息下包含单独的键。 It's simpler to avoid nesting them or keep them on objects that really use them, if that's the case. 如果是这样,避免嵌套它们或将它们保留在真正使用它们的对象上更简单。

 function flattenCarList(prevCars, car) { var Details = car.Details; delete car.Details; var carProto = Object.create(car.prototype || null) var keys = Object.keys(Details); for (var i = 0; i < keys.length; i++) { Details[i] = carProto[i] = keys[i]; } var carSet = []; for (var i = 0; i < Details.length; i++) { carSet.push(new Details[i]); } return prevCars.concat(carSet); } var cars = [{ Make: 'Edzel', Plate: 123456, Details: { Desc: 'Don\\'t ask', Miles: 32, Colour: 'Sickly Green' } }]; // Now let's really get to the point. cars.reduce(flattenCarList); document.getElementById('status').innerHTML += 'RESULTS:<br />' + JSON.stringify(cars); 
 <code id="status"></code> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM