映射后连接嵌套数组

时间:2013-06-12 15:19:37

标签: javascript jquery

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

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 []

预期结果

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

我觉得我错过了一些非常基本的东西。我记录了$.map函数的结果,似乎返回了[]。有人能解决这个问题吗?

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

6 个答案:

答案 0 :(得分:19)

使用直接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};
});

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

答案 1 :(得分:6)

  

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

     

此方法不会更改现有数组,但会返回新数组   array,包含连接数组的值。

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};
    }));
}

答案 2 :(得分:3)

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

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

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

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

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

答案 3 :(得分:2)

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

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

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

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

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));

答案 4 :(得分:1)

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

答案 5 :(得分:1)

更新为flatMap(与 IE 不兼容)

categories.flatMap((categories) => categories.items)

flatMap() 方法返回一个新数组,该数组通过对数组的每个元素应用给定的回调函数,然后将结果展平一级而形成。