12

我有一个包含多个类别对象的数组,每个类别对象都有一个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 []

预期结果

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

我觉得好像我错过了一些非常基本的东西。我记录了$.map函数的结果,它似乎正在返回一个[]. 谁能弄清楚这个问题?

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

4

6 回答 6

25

另一种使用直接 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}, …]

于 2015-07-29T18:09:45.090 回答
9

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

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

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};
    }));
}
于 2013-06-12T15:25:32.777 回答
4
  const items = categories
          .map(category => category.items)
          .reduce((prev, current) => [...prev, ...current])
          .map((e, i) => ({ label: e.name, value: e.itemId }));
于 2020-03-12T18:13:23.713 回答
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,我们将这两个项目数组展平并获得所需的输出。

于 2016-03-26T22:38:13.780 回答
3

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

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));
于 2016-11-19T12:43:46.073 回答
2

更新flatMap(与 IE 不兼容)

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

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

于 2021-01-22T18:03:21.440 回答