根据每个数组中的第一个值合并数组

Posted

技术标签:

【中文标题】根据每个数组中的第一个值合并数组【英文标题】: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 - 我可以请您详细说明或指向一个可能概述您的意思的页面吗?非常感谢 这里有数百个关于合并数组的问题。就算找不到完全一样的,大体的思路也应该是一样的,应该能搞清楚。 【参考方案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 ...您可以查看上面提供的最新方法/解决方案。

以上是关于根据每个数组中的第一个值合并数组的主要内容,如果未能解决你的问题,请参考以下文章

我将如何减少这个数组,以便每个对象中的对象被合并 javascript 但不知道键值名称

php数组根据键名怎么合并呢

合并k个有序数组

根据键的值合并数组

javascript 数组对象根据相同属性值{key:value}合并两个对象

合并数组的值并对重复值求和