将相同长度的数组合并成对象数组

4

我有10个数据数组,看起来像这样:

var arr = [1,2,3,4,5,6,7,8,9,10]
var arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9']
...8 More Arrays

每个数组每次都将拥有完全相同数量的元素。我想知道生成一个看起来像这样并且将各个数组合并在一起的对象数组的最佳方法:
overallarray = [{
arr1 = 1,
arr2 = 'hello'
...
},
{
arr1 = 2,
arr2 = 'hello1'
...
}]

我知道可以使用大量的for循环,但希望找到更优化的解决方案。


你的数据为什么设置成那样? - Jhecht
2
你只需要一个循环,通过重复使用索引从每个数组中复制所需的属性。一个循环,对一个空对象进行多次赋值。 - dandavis
dandavis是正确的 - 如果您确信每个数组的长度完全相同,那么仅循环一次任何一个数组,并简单地重用当前迭代器值将完全满足您的需求。 - Jhecht
@DakotaBrown:我在代码中没有注意到arr1不能作为期望的属性名称,所以我稍微改进了我的答案。你可以考虑使用它,因为它不仅可以很好地扩展,还可以分配不能作为变量名的属性名称,而且更重要的是,它的速度显著更快,特别是对于较大的数据集。 - Yevhen Horbunkov
4个回答

8

这就是 Array.map() 可以发挥作用的地方。您可以通过迭代任何一个数组(因为它们具有相同数量的元素),然后按索引访问每个元素,以获取数据集中每个数组的相应值,如下所示:

var arr = [0,1,2,3,4,5,6,7,8,9]
var arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9'];
var arr3=['foo','foo1','foo2','foo3','foo4','foo5','foo6','foo7','foo8','foo9'];

let mapped = arr.map((elem, index) => {
  return {
    arr1: arr[index],
    arr2: arr2[index],
    arr3: arr3[index]
  }
});

console.log(mapped);

编辑:如果您想通用地访问它们,可以将所有数组添加到一个字典中,并迭代键/值对,如下所示:

var arr = [0,1,2,3,4,5,6,7,8,9]
var arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9'];
var arr3=['foo','foo1','foo2','foo3','foo4','foo5','foo6','foo7','foo8','foo9'];
// combine all arrays into single dataset
let data = {arr, arr2, arr3};

let mapped = arr.map((elem, index) => {
  // iterate over the key/value pairs of the dataset, use the key to generate the 
  // result object key, use the value to grab the item at the current index of the 
  // corresponding array
  return Object.entries(data).reduce((res, [key, value]) => {
    res[key] = value[index];
    return res;
  }, {});
});

console.log(mapped);


2
@Jhecht 我的意思是,你还有什么其他方法可以将这10个数组组合起来呢?它们必须以某种方式手动组合。 - Nicholas Siegmundt
1
@Jhecht 已更新,包括在 .map() 内部通用处理数组的情况。 - mhodges
1
@lainatnavi 从技术上讲?是的。实际上呢?可能不是。应该这样做吗?绝对不应该。 - mhodges
1
@mhodges 这就是我一直在寻找的,为什么我的数据会以如此奇怪的方式移动,我正在集成几个最初没有设计为一起工作的SAAS平台,每个平台都有自己的数据要求,包括格式和功能,我必须解决这些问题。 - Dakota Brown
1
值得注意的是,数组名称不一定是连续的。 - Dakota Brown
显示剩余2条评论

4
假设arr1arr2不是所需的结果对象属性的名称,如果您需要以下内容:
  • 可以很好地扩展到任意数量的数据数组;
  • 分配任意键名称(不一定对应于数组变量名称,或者更糟糕的是,需要属性名称不能是有效的变量名称);
  • 比已接受的解决方案快得多 :)。
您可以执行以下操作:

const arr1 = [1,2,3,4,5,6,7,8,9,10],
      arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9'],
      
      keyNames = ['id', 'greeting'],
      
      group = (...arrays) => (keys) =>
        arrays.reduce((res, arr, idx) => 
          (arr.forEach((e,i) => res[i][keys[idx]] = e), res), 
          Array.from({length:arrays[0].length}, () => ({}))
        )
      
console.log(group(arr1,arr2)(keyNames))
.as-console-wrapper {min-height:100%;}


1
只需使用一个循环计数器遍历所有数组:
    var dataArrayOne = [1, 2, 3, 4 ];
    var dataArrayTwo = ["hello", "hello1", "hello2", "hello3" ];
...

    var resultArray = [];

    for (var i = 0; i < 4; i++)
    {
        var combined = {
            arr1: dataArrayOne[I],
            arr2: dataArrayTwo[i]
...
        };

        resultArray.push(combined);
    }

1

你可以从这里获得:

[  [1, 2, 3]
,  [4, 5, 6]
,  [7, 8, 9]
]

转换为:

[  [1, 4, 7]
,  [2, 5, 8]
,  [3, 6, 9]
]

使用此函数:
const combine =
  (...arrs) =>
    [ arrs.map(xs => xs[0])
    , ... (  arrs.every(xs => xs.length === 1)
              ? []
              : combine(...arrs.map(xs => xs.slice(1)))
          )
    ];


combine
  (  [1, 2, 3]
  ,  [4, 5, 6]
  ,  [7, 8, 9]
  );

然后从这个开始:

[  [1, 4, 7]
,  [2, 5, 8]
,  [3, 6, 9]
]

转换为:

[ {arr1: 1, arr2: 4, arr3: 7}, {arr1: 2, arr2: 5, arr3: 8}, {arr1: 3, arr2: 6, arr3: 9}]

使用此函数:
const to_obj =
  (...arrs) =>
    arrs.map(arr =>
      Object.fromEntries(
        arr.map((x, i) => [`arr${i+1}`, x])));

to_obj
  ( [1, 4, 7]
  , [2, 5, 8]
  , [3, 6, 9]
  )

希望将这两个功能连接在一起很简单。

关于性能的说明

对于正好有10个元素的10个数组,很难判断哪种解决方案比另一种表现更好。您应该选择在可读性或维护方面感觉正确的解决方案。

按照这些标准,您应该排除我的解决方案;我只是想分享一种不同的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接