javascript 映射后连接嵌套数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17069223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 06:59:27  来源:igfitidea点击:

Concatenate Nested Array after Mapping

javascriptjquery

提问by Kevin Bowersox

I have an array with several category objects, each of which has an itemsproperty containing an array of item objects. I want to map each item in each category to an object[] with objects that have the properties value and label. For some reason, I can't perform the concatenation.

我有一个包含多个类别对象的数组,每个类别对象都有一个items包含项目对象数组的属性。我想将每个类别中的每个项目映射到具有属性值和标签的对象的 object[]。出于某种原因,我无法执行串联。

var categories = [{
                name: "category1",
                items: [{
                    itemId: 1,
                    name: "Item1"
                }, {
                    itemId: 2,
                    name: "Item2"
                }]
            }, {
                name: "category2",
                items: [{
                    itemId: 3,
                    name: "Item3"
                }, {
                    itemId: 4,
                    name: "Item4"
                }]
            }];

var items = [];
for(var i = 0; i < categories.length; i++){
    items.concat($.map(categories[i].items,function(elem){
        return {value:elem.itemId, label:elem.name};
    }));
} 
console.log(items); //prints []

Expected Result

预期结果

[{
   label: "Item1",
   value: "1"
},
{
   label: "Item2",
   value: "2"
},{
   label: "Item3",
   value: "3"
},{
   label: "Item4",
   value: "4"
}

I feel as if I am missing something very basic. I logged the result of the $.mapfunction and it appears to be returning an []. Can anyone figure out the issue?

我觉得好像我错过了一些非常基本的东西。我记录了$.map函数的结果,它似乎返回了一个[]. 任何人都可以弄清楚这个问题吗?

JSFiddle:http://jsfiddle.net/vymJv/

JSFiddle:http : //jsfiddle.net/vymJv/

采纳答案by A. Wolff

The concat() method is used to join two or more arrays.

This method does not change the existing arrays, but returns a new array, containing the values of the joined arrays.

concat() 方法用于连接两个或多个数组。

此方法不会更改现有数组,而是返回一个新数组,其中包含连接数组的值。

http://jsfiddle.net/vymJv/1/

http://jsfiddle.net/vymJv/1/

for(var i = 0; i < categories.length; i++){
    items = items.concat($.map(categories[i].items, function(elem) {
        return {value: elem.itemId, label: elem.name};
    }));
}

回答by y2knoproblem

Another method using straight Javascript:

使用直接 Javascript 的另一种方法:

var x = categories.map(function(val) {
  return val.items;
}).reduce(function(pre, cur) {
   return pre.concat(cur);
}).map(function(e,i) {
  return {label:e.name,value:e.itemId};
});

Output: x = [{label: "Item1", value: 1}, {label: "Item2", value: 2}, …]

输出: x = [{label: "Item1", value: 1}, {label: "Item2", value: 2}, …]

回答by itsbriany

We could extend the array prototype by creating concatAllwhich will concatenate all of your arrays by iterating over each subarray, dumping each value into a new array.

我们可以通过创建concatAll来扩展数组原型,它将通过迭代每个子数组来连接所有数组,将每个值转储到一个新数组中。

Array.prototype.concatAll = function() {
  var results = [];
  this.forEach(function(subArray) {
    subArray.forEach(function(subArrayValue) {
      results.push(subArrayValue);
    });
  });
  return results;
};

Then, we can get the desired result with the following:

然后,我们可以通过以下方式获得所需的结果:

let items = categories.map(function(category) {
  return category.items.map(function(item) {
    return {label: item.name, value: item.itemId};
  });
}).concatAll();

We get the items by translating each category into an array of items. Because we have two categories, we will end up with two arrays of items. By applying concatAllon the final result, we flatten those two arrays of items and get the desired output.

我们通过将每个类别转换为项目数组来获取项目。因为我们有两个类别,所以我们最终会得到两个项目数组。通过对最终结果应用concatAll,我们将这两个项目数组展平并获得所需的输出。

回答by luxcoder

This piece of code solves your task using a functional programming approach:

这段代码使用函数式编程方法解决了您的任务:

var items = [].concat.apply([], categories.map(cat =>
  cat.items.map(elem => ({ value:elem.itemId, label:elem.name })))
)

Explanation: Function.prototype.apply()has the syntax fun.apply(thisArg, [argsArray])and lets us provide parameters to a function in an array. Array.prototype.concat()combines an arbitrary amount of parameters into one array. If we now write Array.prototype.concat.apply([], [category1Items, ..., categoryNItems]), it actually equals [].concat(category1Items, ..., categoryNItems), which concatenates all parameters together. You can also replace Array.prototype.concatby [].concatto keep it shorter. Otherwise we just use standard mapping to get the job done.

说明:Function.prototype.apply()有语法fun.apply(thisArg, [argsArray]),让我们为数组中的函数提供参数。Array.prototype.concat()将任意数量的参数组合成一个数组。如果我们现在写Array.prototype.concat.apply([], [category1Items, ..., categoryNItems]),它实际上等于[].concat(category1Items, ..., categoryNItems),它将所有参数连接在一起。您也可以替换Array.prototype.concat[].concat以使其更短。否则我们只是使用标准映射来完成工作。

You could also split the code apart a bit more for clarity:

为了清楚起见,您还可以将代码分开一点:

function getItem(elem){
  return {value:elem.itemId, label:elem.name};
}

function getCategoryItems(cat) {
  return cat.items.map(getItem);
}

function flatten(arr) {
  return Array.prototype.concat.apply([], arr);
}

var items = flatten(categories.map(getCategoryItems));

回答by Dailenis González Frómeta

  const items = categories
          .map(category => category.items)
          .reduce((prev, current) => [...prev, ...current])
          .map((e, i) => ({ label: e.name, value: e.itemId }));