我有一个像下面这样的javascript结构(嵌套的对象数组)
var categoryGroups = [
{
Id: 1, Categories: [
{ Id: 1 },
{ Id: 2 },
]
},
{
Id: 2, Categories: [
{ Id: 100 },
{ Id: 200 },
]
}
]
我想找到一个匹配Id的子类别对象,假设类别ID都是唯一的。
我在下面有这个,但是想知道是否有更简洁的方法:
var category, categoryGroup, found = false;
for (i = 0; i < categoryGroups.length ; i++) {
categoryGroup = categoryGroups[i];
for (j = 0; j < categoryGroup.Categories.length; j++) {
category = categoryGroup.Categories[j];
if (category.Id === id) {
found = true;
break;
}
}
if (found) break;
}
答案 0 :(得分:8)
警告:这会使用仅在ECMAScript 5中添加的几个Array.prototype
函数,因此除非您将其填充,否则无法使用旧版浏览器。
您可以遍历数组中的所有第一级对象,然后根据条件过滤类别并收集数组中的所有匹配项。您的最终结果将是匹配数组中的第一个元素(如果数组为空,则找不到匹配项)。
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
console.log(matches[0] || "Not found");
JSFiddle: http://jsfiddle.net/b7ktf/1/
参考:
Array.prototype.forEach
Array.prototype.concat
Array.prototype.filter
答案 1 :(得分:5)
在ES2019中使用flatMap
const category = categoryGroups.flatMap(cg => cg.Categories).find(c => c.Id === categoryId);
答案 2 :(得分:1)
检查fiddle
中的代码var categoryGroups = [
{
Id: 1, Categories: [
{ Id: 1 },
{ Id: 2 },
]
},
{
Id: 2, Categories: [
{ Id: 100 },
{ Id: 200 },
]
}
]
var id = 100;
var x = 'not found';
var category, categoryGroup, found = false;
for (i = 0; i < categoryGroups.length ; i++) {
categoryGroup = categoryGroups[i];
for (j = 0; j < categoryGroup.Categories.length; j++) {
category = categoryGroup.Categories[j];
if (category.Id == id) {
var x = category.Id;
found = true;
break;
}
}
if (found) break;
}
alert(x);
上面的代码检查是否在数组中找到了id = 100。如果发现将警告值,否则警报未找到。价值&#39; 100&#39;为了演示而被硬编码
答案 3 :(得分:1)
你可以将它包装在一个函数中以摆脱笨拙的break;
语法,你可以将每个元素加载到for(;;)
构造内的一个变量中,以减少几行。
function subCategoryExists(groups, id)
{
for (var i = 0, group; group = groups[i]; ++i) {
for (var k = 0, category; category = group.Categories[k]; ++k) {
if (category.Id == id) {
return true;
}
}
}
return false;
}
var found = subCategoryExists(categoryGroups, 100);
答案 4 :(得分:1)
使用NodeJS的lodash库(假设您正在使用NodeJS)的简单方法:
const _ = require('lodash');
let category ;
let categoryGroup = _.find(categoryGroups, (element)=>{
category = _.find(element.Categories, {Id : 100});
return category;
});
console.log(categoryGroup); // The category group which has the sub category you are looking for
console.log(category); // The exact category you are looking for
答案 5 :(得分:1)
使用reduce和递归:
function nestedSearch(value) {
return categoryGroups.reduce(function f(acc, val) {
return (val.Id === value) ? val :
(val.Categories && val.Categories.length) ? val.Categories.reduce(f, acc) : acc;
});
}
答案 6 :(得分:1)
仅使用Array.prototype.filter()
:
如果您确定要查找的ID存在,则可以执行以下操作:
var id = 200; // surely it exists
var category = arr.filter(g => g.Categories.filter(c => c.Id === id)[0])[0].Categories.filter(c => c.Id === id)[0];
如果不确定它是否存在:
var id = 201; // maybe it doesn't exist
var categoryGroup = arr.filter(e => e.Categories.filter(c => c.Id === id)[0])[0];
var category = categoryGroup ? categoryGroup.Categories.filter(c => c.Id === id)[0] : null;
答案 7 :(得分:0)
您可以使用underscore:
var cat = _(categoryGroups).
chain().
pluck('Categories').
flatten().
findWhere({Id: 2}).
value();
我在这里做的是,我在一个数组中提取所有Categories
值,然后重新选择正确的类别。
编辑:抱歉,第一次没有问你的问题。正如评论所暗示的那样,你可能不想仅仅使用下划线,但这就是我将如何做到的:)
答案 8 :(得分:0)
如果您想实际返回内部类别(而不只是检查其是否存在),可以使用reduce
:
return categoryGroups.reduce((prev, curr) => {
//for each group: if we already found the category, we return that. otherwise we try to find it within this group
return prev || curr.Categories.find(category => category.Id === id);
}, undefined);
这会短路内部类别,并触摸每个类别组一次。也可以将其修改为categoryGroups上的短路标志。
答案 9 :(得分:0)
我们现在使用object-scan进行数据处理。一旦将头缠绕在它上,它就会非常强大。对于您的问题,它看起来像这样:
const objectScan = require('object-scan');
const lookup = (id, data) => objectScan(['Categories.Id'], {
useArraySelector: false,
abort: true,
rtn: 'parent',
filterFn: ({ value }) => value === id
})(data);
const categoryGroups = [{
Id: 1,
Categories: [{ Id: 1 }, { Id: 2 }]
}, {
Id: 2,
Categories: [{ Id: 100 }, { Id: 200 }]
}];
console.log(lookup(1, categoryGroups));
// => { Id: 1 }
console.log(lookup(100, categoryGroups));
// => { Id: 100 }
console.log(lookup(999, categoryGroups));
// => undefined