【问题标题】:Merge arrays based on first value within each array根据每个数组中的第一个值合并数组
【发布时间】:2022-01-01 08:11:27
【问题描述】:

我有一个如下所示的数组:

var arr = [
[
    "2021-07-31T00:00:00Z",
    "648429a0-00e5-4752-9d84-2857a0ea0787"
],
[
    "2021-08-31T00:00:00Z",
    "648429a0-00e5-4752-9d84-2857a0ea0787"
],
[
    "2021-07-31T00:00:00Z",
    "AAAA"
],
[
    "2021-08-31T00:00:00Z",
    "BBBB"
]

]

我想根据每个数组的第一个值(日期)来转换它。因此,如果日期匹配,它们将合并为一个。所以我想要得到的输出是

[
[
    "2021-07-31T00:00:00Z",
    "648429a0-00e5-4752-9d84-2857a0ea0787",
    "AAAA"
],
[
    "2021-08-31T00:00:00Z",
    "648429a0-00e5-4752-9d84-2857a0ea0787",
     "BBBB"
]

]

很高兴知道在这种情况下最好的方法是什么。

【问题讨论】:

  • 请添加您的代码。什么不起作用?
  • 使用键为第一个值的对象。
  • 据我所知,但我认为问题是我真的坚持如何最好地处理它,而不是代码不起作用。 uniqueDates.forEach((date) => { arrMaster.forEach((item) => { if(item[0] == date){ // 做某事 } }) }
  • @barmar - 我可以请您详细说明或指向一个可能概述您的意思的页面吗?非常感谢
  • 这里有数百个关于合并数组的问题。就算找不到完全一样的,大体的思路也应该是一样的,应该能搞清楚。

标签: javascript arrays merge reduce


【解决方案1】:

使用映射覆盖在数组中找到的值。然后使用Object.entries() 创建最终数组:


var original = [ [1,2], [1,3], [2,3]]
var final = []
var map = {}

original.forEach(a => {
    if (!map[a[0]]) { map[a[0]] = [] }
    map[a[0]].push(a[1]);
});
Object.entries(map).forEach(e => final.push([e[0], ...e[1]]))

编辑:更改答案以获取所有值

【讨论】:

  • 非常感谢。然而,我发现输出显示为 [ [ "1", 3 ], [ "2", 3 ] ]。有没有办法让数组像下面这样输出(这样两个值都包括在内)? [ [ "1", 2, 3 ], [ "2", 3 ] ]
  • 您只需要修改数据在地图中的存储方式即可。编辑答案以反映这一点
  • 这很完美!再次感谢 - 将非常有用
  • @user2547766 ...虽然上述方法有效,但它依赖于forEach回调函数之外的引用。此外,它还需要另外两个完整的迭代周期(Object.entriesforEach)才能累积最终结果,而且,forEach 回调需要知道来自外部范围的 final 引用.因此,此类方法永远不会提供可重用的功能。
【解决方案2】:

你可以试试这个reduce方法

    var arr = [
    [
        "2021-07-31T00:00:00Z",
        "648429a0-00e5-4752-9d84-2857a0ea0787"
    ],
    [
        "2021-08-31T00:00:00Z",
        "648429a0-00e5-4752-9d84-2857a0ea0787"
    ],
    [
        "2021-07-31T00:00:00Z",
        "AAAA"
    ],
    [
        "2021-08-31T00:00:00Z",
        "BBBB"
    ]
];

arr = arr.reduce((a, i) => {
    if (!a) a = [];
    var found = false;
    a.forEach(ai => {
        if (ai[0] == i[0]) {
            found = true;
            for (var k = 0; k < i.length; k++) {
                if (k > 0)
                    ai.push(i[k]);
            }
        }
    });
    if (!found)
        a.push(i);
    return a;
}, []);

【讨论】:

    【解决方案3】:

    无需在单个reduce 循环内进行嵌套迭代即可完成 OP 的任务。

    基本方法是使用定制对象作为累加器/收集器。这样的收集器具有 2 个属性 ...index 用作基于 Object 的分组数组的映射/查找,其中组键始终是每个(待处理的)数组的第一项...和...@ 987654325@ 将保存上述(尚未创建)分组数组的引用,其中总是将当前处理的数组的第二项推入。

    var arr = [[
      "2021-07-31T00:00:00Z",
      "648429a0-00e5-4752-9d84-2857a0ea0787",
    ], [
      "2021-08-31T00:00:00Z",
      "648429a0-00e5-4752-9d84-2857a0ea0787",
    ], [
      "2021-07-31T00:00:00Z",
      "AAAA",
    ], [
      "2021-08-31T00:00:00Z",
      "BBBB",
    ]];
    
    function collectAndAggregateGroupedArrays(collector, item) {
      const { index, result } = collector;
    
      let groupKey = item[0];
      let groupedList = index[groupKey];
    
      if (!groupedList) {
        groupedList = index[groupKey] = [groupKey];
    
        result.push(groupedList);
      }
      groupedList.push(item[1]);
    
      return collector;
    }
    console.log(
      arr.reduce(collectAndAggregateGroupedArrays, {
    
        index: {},
        result: [],
    
      }).result
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    【讨论】:

    • @user2547766 ...您可以查看上面提供的最新方法/解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-02-11
    • 2017-04-14
    • 2019-01-27
    • 2019-05-29
    • 2021-04-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多