【问题标题】:Merging two array objects of different lengths on value在值上合并两个不同长度的数组对象
【发布时间】:2015-05-29 11:09:58
【问题描述】:

我需要一些帮助来完成一项相当简单但具有挑战性的(对我来说:)编程任务。

有两个数组对象,一长一短:

var arrayShort = [
  {
    id: 'A',
    name: 'first'
  },{
    id: 'B',
    name: 'second'
  },{
    id: 'C',
    name: 'third'
  }
]

var arrayLong = [
  {
    id: 'A',
    name: 'firstSub1'
  },{
    id: 'A',
    name: 'firstSub2'
  },{
    id: 'A',
    name: 'firstSub3'
  },{
    id: 'B',
    name: 'secondSub1'
  },{
    id: 'B',
    name: 'secondSub2'
  },{
    id: 'B',
    name: 'secondSub3'
  },{
    id: 'C',
    name: 'thirdSub1'
  },{
    id: 'C',
    name: 'thirdSub2'
  },{
    id: 'C',
    name: 'thirdSub3'
  }
]

我如何根据共享 ID 将它们合并在一起,以获得以下信息:

var arrayCombined = [
  {
    id: 'A',
    name: 'first'
  },{
    id: 'A',
    name: 'firstSub1'
  },{
    id: 'A',
    name: 'firstSub2'
  },{
    id: 'A',
    name: 'firstSub3'
  },{
    id: 'B',
    name: 'second'
  },{
    id: 'B',
    name: 'secondSub1'
  },{
    id: 'B',
    name: 'secondSub2'
  },{
    id: 'B',
    name: 'secondSub3'
  },{
    id: 'C',
    name: 'third'
  },{
    id: 'C',
    name: 'thirdSub1'
  },{
    id: 'C',
    name: 'thirdSub2'
  },{
    id: 'C',
    name: 'thirdSub3'
  },
]

重要

顺序很重要。

我尝试过的

for (var i = 0; i < arrayShort.length; i++) {
  var itemShort = arrayShort[i]
  console.log(itemShort)
  for (var j = 0; j < arrayLong.length; j++) {
        var itemLong = arrayLong[j]
    if (itemLong.id === itemShort.id) {
      console.log(itemLong)
      arrayShort.splice(j + 1, 0, arrayLong)
    }
  }
}


var arrayCombined = arrayShort
console.log(arrayCombined)

这会导致无限循环,但我不知道为什么。一般来说,我知道嵌套循环和条件是坏消息。

有什么更好的方法来解决这个问题(精神上,使用代码等)?

Here's a Codepen,打开开发工具看看

注意事项:

  • 首选Vanilla Javascript 解决方案,但最好看看使用Lodash 或Underscores 执行此操作的方法。一般来说,我觉得这两个库中的任何一个都可以使这种类型的任务变得超级简单,但我似乎永远无法弄清楚到底是如何做到的。
  • 尝试为此找到正确的搜索词非常困难...建议?

感谢反馈/见解。

【问题讨论】:

  • 由于两个列表似乎都已排序且顺序相同,因此请使用 en.wikipedia.org/wiki/Merge_algorithm
  • arrayShort.splice(j + 1, 0, arrayLong) 是个坏主意。最好尝试构建一个新数组,它更容易更干净。
  • @Bergi 感谢您向我指出合并算法。是的,我当然看到拼接,尤其是在嵌套丛林中,是一种不好的方法 - 因此我提出了这个问题。
  • 另外,很重要的一点是要指出这些来自同一个大 json blob,我正在接收并需要从外部 API 解析成我想要的数据结构。跨度>
  • @IsaacGregson 如果您期望一个大的 json blob,那么我认为您不应该采用排序方法。那是更少的代码,但你会为性能付出代价。

标签: javascript arrays json loops lodash


【解决方案1】:

concat 和 sort 是你的朋友

var arrayCombined = (arrayShort.concat(arrayLong).sort(function(a,b) {


            return (a.id > b.id) ?  1 : 
                  ((a.id < b.id) ? -1 : 0);

})).sort(function(a,b) {

            return (a.name > b.name) ?  1 : 
                  ((a.name < b.name) ? -1 : 0);

});;

console.log(arrayCombined);

这是输出

[ { id: 'A', name: 'first' },
  { id: 'A', name: 'firstSub1' },
  { id: 'A', name: 'firstSub2' },
  { id: 'A', name: 'firstSub3' },
  { id: 'B', name: 'second' },
  { id: 'B', name: 'secondSub1' },
  { id: 'B', name: 'secondSub2' },
  { id: 'B', name: 'secondSub3' },
  { id: 'C', name: 'third' },
  { id: 'C', name: 'thirdSub1' },
  { id: 'C', name: 'thirdSub2' },
  { id: 'C', name: 'thirdSub3' } ]

【讨论】:

  • 注意:这是非常低效的。因为它必须对大型数据集进行 O(N lg N) 排序。
  • 在实施这种方法一段时间后,我注意到这里(以及在我的结果中)secondthird 不在他们列表的顶部......这意味着这种方法不起作用!正如我在问题中提到的,顺序很重要。想法?
  • 更新:首先按 id 排序,然后按其他属性
【解决方案2】:

使用 lodash,您可以执行以下操作:

var arrayShort = [
    { id: 'A', name: 'first' },
    { id: 'B', name: 'second' },
    { id: 'C', name: 'third' }
];

var arrayLong = [
    { id: 'A', name: 'firstSub1' },
    { id: 'A', name: 'firstSub2' },
    { id: 'A', name: 'firstSub3' },
    { id: 'B', name: 'secondSub1' },
    { id: 'B', name: 'secondSub2' },
    { id: 'B', name: 'secondSub3' },
    { id: 'C', name: 'thirdSub1' },
    { id: 'C', name: 'thirdSub2' },
    { id: 'C', name: 'thirdSub3' }
];

_(arrayShort)
    .union(arrayLong)
    .sortByAll('id', 'name')
    .value()
// →
// [
//   { id: 'A', name: 'first' },
//   { id: 'A', name: 'firstSub1' },
//   { id: 'A', name: 'firstSub2' },
//   { id: 'A', name: 'firstSub3' },
//   { id: 'B', name: 'second' },
//   { id: 'B', name: 'secondSub1' },
//   { id: 'B', name: 'secondSub2' },
//   { id: 'B', name: 'secondSub3' },
//   { id: 'C', name: 'third' },
//   { id: 'C', name: 'thirdSub1' },
//   { id: 'C', name: 'thirdSub2' },
//   { id: 'C', name: 'thirdSub3' }
// ]

union() 是一种连接两个数组且不会产生副作用的廉价方法,sortByAll() 可让您按多个属性名称进行排序。

【讨论】:

  • +1。在看到这个之前,我已经达到了同样的方法。为什么?主要是因为我有一些其他的关系(子小节)需要包括在内,Lodash 的flatten 确实很神奇。
猜你喜欢
  • 2019-10-25
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
  • 2021-11-19
  • 2019-02-27
  • 1970-01-01
  • 2021-04-27
  • 1970-01-01
相关资源
最近更新 更多