【问题标题】:Join two objects by key键连接两个对象
【发布时间】:2016-10-07 06:27:04
【问题描述】:

我坚持将 2 个对象合并为一个。假设我有 2 个对象数组: 一个是孩子:

let childsWithMoreInfo = [{
  id: 1,
  name: 'somename',
  parent: {
    id: 2
  },
}, {
  id: 2,
  name: 'some child name',
  parent: {
    id: 4
  }
}];

第二个是父母:

let parents = [{
  id: 1,
  parentName: 'The first',
  child: {}
}, {
  id: 2,
  parentName: 'The second',
  child: {}
}, {
  id: 3,
  parentName: 'The third',
  child: {}
}, {
  id: 4,
  parentName: 'The fourth',
  child: {}
}];

我会像这样合并这些对象:

        let combined = [
            {
                id: 1,
                parentName: The first,
                child: {}
            },
            {
                id: 2,
                parentName: The second,
                child: {
                    id: 1,
                    name: somename,
                }
            },
            {
                id: 3,
                parentName: The third,
                child: {}
            },
            {
                id: 4,
                parentName: The fourth,
                child: {
                    id: 2
                    name: some child name,
                }
            },

        ]
        ];

所以基本上它应该是这样的: let combinedList = parents.child = childsWithMoreInfo where parents.id = childsWithMoreInfo.parent.id 。我应该看看哪种方法?您有什么想法可以轻松实现吗?

【问题讨论】:

  • 它们被合并为子元素。
  • 我建议您查看 lodash lodash.com/docs/4.16.4。它们具有各种功能,可以在不同条件下合并数组。您当然可以自己构建一个合并,循环中的循环。
  • @crotoan 重读问题。
  • 我已经看过很多遍了,但不知道我可以使用哪种方法:(

标签: javascript ecmascript-6 lodash


【解决方案1】:

我真的知道如何使用 forEach,我想避免它。

这是我做的:

    this.combined = _.map(parents, (parent) => {
            parent.child = childs.find(child => child.parent.id === parent.id);
        return parent;
    });

感谢您的所有回答。

【讨论】:

  • 为什么不用内置JS数组的map
  • 有什么理由比Array.prototype.map更喜欢它?
【解决方案2】:

您可以使用Map,然后对每个对象使用Array#forEach 进行迭代。

然后在地图中查找并将值分配给 ch 父对象。

var childsWithMoreInfo = [{ id: 1, name: 'somename', parent: { id: 2 } }, { id: 2, name: 'some child name', parent: { id: 4 } }],
    parents = [{ id: 1, parentName: 'The first', child: {} }, { id: 2, parentName: 'The second', child: {} }, { id: 3, parentName: 'The third', child: {} }, { id: 4, parentName: 'The fourth', child: {} }],
    map = new Map;

parents.forEach(p => map.set(p.id, p));
childsWithMoreInfo.forEach(c => {
    var o = map.get(c.parent.id);
    o.child = { id: c.id, name: c.name };
});
console.log(parents);
.as-console-wrapper { max-height: 100% !important; top: 0; }

另一种解决方案是使用Array#find

var childsWithMoreInfo = [{ id: 1, name: 'somename', parent: { id: 2 } }, { id: 2, name: 'some child name', parent: { id: 4 } }],
    parents = [{ id: 1, parentName: 'The first', child: {} }, { id: 2, parentName: 'The second', child: {} }, { id: 3, parentName: 'The third', child: {} }, { id: 4, parentName: 'The fourth', child: {} }];

childsWithMoreInfo.forEach(c => {
    var o = parents.find(p => p.id === c.parent.id);
    o.child = { id: c.id, name: c.name };
});
console.log(parents);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 与使用 for/forEach 迭代 JSON 数组相比,使用 Map 有什么性能改进?
  • map 有 o(1),但你可以用 find 代替。
  • @AniketSinha 这不是一个“json 数组”,而只是一个 javascript 数组。
【解决方案3】:

以下代码有一些纯函数来完成您的任务。我还格式化/清理了输入对象:

'use strict';

let childsWithMoreInfo = [{
  id: 1,
  name: 'somename',
  parent: {
    id: 2
  },
}, {
  id: 2,
  name: 'some child name',
  parent: {
    id: 4
  }
}];

let parents = [{
  id: 1,
  parentName: 'The first',
  child: {}
}, {
  id: 2,
  parentName: 'The second',
  child: {}
}, {
  id: 3,
  parentName: 'The third',
  child: {}
}, {
  id: 4,
  parentName: 'The fourth',
  child: {}
}];

function makeObjectFromArray(arr) {
  let obj = {};
  arr.map(function(item) {
    if (obj[item.id] === undefined) {
      obj[item.id] = item
    }
  })
  return obj;
}

function toArray(obj) {
  return Object.keys(obj).map(function(key) {
    return obj[key]
  });
}

function sampleParentChildren(parent, children) {
  let Parent = {};
  if (parent.constructor === Array) {
    Parent = makeObjectFromArray(parent);
  } else {
    Parent = Object.assign({}, parent)
  }
  children.map(function(child) {
    if (Parent[child.parent.id] !== undefined) {
      if (Parent[child.parent.id].child === undefined) {
        Parent[child.parent.id].child = {};
      }
      Parent[child.parent.id].child[child.id] = child
    }

  });
  return Parent;
}
let resampledData = sampleParentChildren(parents, childsWithMoreInfo);
console.log(resampledData, toArray(resampledData));

【讨论】:

    【解决方案4】:

    要在 ES6 中加入数组,您可以使用扩展运算符来加入数组,只需使用普通的旧 forEach 进行重复数据删除。扩展运算符比 Es5 的数组连接方法更具声明性,如 MDN 上的 here 所述

    [...parents, ...childsWithMoreInfo]
    

    这是一个工作示例:

    let childsWithMoreInfo = [{
        id: 1,
        name: 'somename',
        parent: {
          id: 2
        },
      }, {
        id: 2,
        name: 'some child name',
        parent: {
          id: 4
        }
      }],
      parents = [{
          id: 1,
          parentName: 'The first',
          child: {}
        }, {
          id: 2,
          parentName: 'The second',
          child: {}
        }, {
          id: 3,
          parentName: 'The third',
          child: {}
        }, {
          id: 4,
          parentName: 'The fourth',
          child: {}
        },
    
      ];
    
    var conjoined = [...parents, ...childsWithMoreInfo];
    
    conjoined.forEach(function(parentConjoinee, parentIndex) {
      conjoined.forEach(function(childConjoinee, childIndex) {
        if (parentConjoinee.id === childConjoinee.id && parentIndex !== childIndex) {
          conjoined.splice(childIndex, 1);
        }
      });
    });
    
    console.log(conjoined);

    【讨论】:

      【解决方案5】:

      你可以使用嵌套的for循环,break

      var childsWithMoreInfo = [{
        id: 1,
        name: "somename",
        parent: {
          id: 2
        }
      }, {
        id: 2,
        name: "some child name",
        parent: {
          id: 4
        }
      }];
      
      var parents = [{
          id: 1,
          parentName: "The first",
          child: {}
        }, {
          id: 2,
          parentName: "The second",
          child: {}
        }, {
          id: 3,
          parentName: "The third",
          child: {}
        }, {
          id: 4,
          parentName: "The fourth",
          child: {}
        }
      
      ];
      let combined = [];
      for (var i = 0; i < parents.length; i++) {
        for (var j = 0; j < childsWithMoreInfo.length; j++) {
          if (childsWithMoreInfo[j].parent.id === parents[i].id) {
            parents[i].child.id = childsWithMoreInfo[j].id;
            parents[i].child.name = childsWithMoreInfo[j].name;
            break;
          }
        }
        combined.push(parents[i])
      };
      
      console.log(combined);

      【讨论】:

      • 我会采用相同的方法,因为它更简单,除非有人证明使用地图的性能改进。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2017-02-09
      • 1970-01-01
      • 2015-01-05
      • 2016-08-25
      • 1970-01-01
      相关资源
      最近更新 更多