[英]Filtering array of objects by searching nested object properties
I have an array of objects that I want to filter by comparing a nested property to a search term. 我有一个对象数组,我想通过比较嵌套属性和搜索词来过滤。
For example: 例如:
var array = [
{category: 'Business'
users: [
{name: 'Sally'
tags: [{tag: 'accounting'}, {tag: 'marketing'},...]
},
{name: 'Bob'
tags: [{tag: 'sales'}, {tag: 'accounting'},...]
}...
]
},
{category: 'Heritage'
users: [
{name: 'Linda'
tags: [{tag: 'Italy'}, {tag: 'Macedonia'},...]
},
{name: 'George'
tags: [{tag: 'South Africa'}, {tag: 'Chile'},...]
},...
]
},...
[
Essentially I want to filter the base array of objects by a search terms that include characters from the tag property string in the nested objects 2 arrays down. 基本上我想通过搜索项过滤对象的基础数组,搜索项包括嵌套对象2数组中的标记属性字符串中的字符。
So a search for 'market' would result in 因此,搜索“市场”将导致
[
{category: 'Business'
users: [
{name: 'Sally'
tags: [{tag: 'accounting'}, {tag: 'marketing'},...]
},
{name: 'Bob'
tags: [{tag: 'sales'}, {tag: 'accounting'},...]
}...
]
}
]
Thank you. 谢谢。
You could use Array#filter
with looking into the nested arrays by using Array#some
. 您可以使用
Array#filter
通过使用Array#some
查看嵌套数组。
If the tag is found in a nested array, then iteration stops and the result is given back to the filter callback. 如果在嵌套数组中找到标记,则迭代停止并将结果返回给过滤器回调。
var array = [{ category: 'Business', users: [{ name: 'Sally', tags: [{ tag: 'accounting' }, { tag: 'marketing' }] }, { name: 'Bob', tags: [{ tag: 'sales' }, { tag: 'accounting' }] }] }, { category: 'Heritage', users: [{ name: 'Linda', tags: [{ tag: 'Italy' }, { tag: 'Macedonia' }] }, { name: 'George', tags: [{ tag: 'South Africa' }, { tag: 'Chile' }] }] }], tag = 'marketing', result = array.filter(a => a.users.some(u => u.tags.some(t => t.tag.includes(tag)))); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this: 尝试这个:
function search(term){
return
Array.filter(array,function(item){
return JSON.stringify(obj).indexOf(term)!=-1;
});
}
So : 所以:
console.log(search('market'));
I hope to be helpful for you:) 我希望对你有所帮助:)
The solution using Array.prototype.some()
function: 使用
Array.prototype.some()
函数的解决方案:
var arr = [{ category: 'Business', users: [{ name: 'Sally', tags: [{ tag: 'accounting' }, { tag: 'marketing' }] }, { name: 'Bob', tags: [{ tag: 'sales' }, { tag: 'accounting' }] }] }, { category: 'Heritage', users: [{ name: 'Linda', tags: [{ tag: 'Italy' }, { tag: 'Macedonia' }] }, { name: 'George', tags: [{ tag: 'South Africa' }, { tag: 'Chile' }] }] }], search_key = 'market', result = []; arr.forEach(function(o){ if (o.users.some(function(v){ return v.tags.some(function(i){ return i.tag.indexOf(search_key) !== -1; }); })) { result.push(o); } }); console.log(result);
The concatAll
and concatMap
definitions are taken from http://reactivex.io/learnrx/ concatAll
和concatMap
定义取自http://reactivex.io/learnrx/
Array.prototype.concatAll = function() {
var results = [];
this.forEach(function(subArray) {
results.push.apply(results, subArray);
});
return results;
};
Array.prototype.concatMap = function(projectionFunctionThatReturnsArray) {
return this.
map(function(item) {
return projectionFunctionThatReturnsArray(item);
}).
// apply the concatAll function to flatten the two-dimensional array
concatAll();
};
function filterByTags(keyword) {
return array.filter(function (item) {
var allTags = item.users.concatMap(function (user) {
return user.tags.map(function (tag) {
return tag.tag;
});
});
return allTags.some(function (tag) {
return tag.indexOf(keyword) > -1;
});
});
}
console.log(filterByTags('market'));
Of course you could inline the allTags
variable for more conciseness. 当然,您可以内联
allTags
变量以获得更简洁。
The filter
applied to the initial array will return all items that have users whose tags contain the keyword supplied. 应用于初始数组的
filter
将返回所有具有标记包含所提供关键字的用户的项目。 The strategy is to build a flattened version of the users' tags and apply some
on that. 策略是构建用户标签的扁平版本并在其上应用
some
。
You can use array.filter
like this: 您可以像这样使用
array.filter
:
function getFiltered(val) {
return array.filter(category == val);
}
This function will return a new array instance, only with the category
keys you passed as the val
params. 此函数将返回一个新的数组实例,仅使用作为
val
参数传递的category
键。
Note: I am taking a shortcut-like approach to this, primarily to provide a different perspective to the problem. 注意:我采用类似快捷方式的方法,主要是为问题提供不同的视角。
Instead of deep-searching the properties and arrays under the main array
, you can create a json string of the users
property and search within that. 您可以创建
users
属性的json字符串并在其中进行搜索,而不是深入搜索主array
下的属性和数组。 So I have created a new property usersString
that temporarily stores the JSON string of the value against users
property. 所以我创建了一个新属性
usersString
,它临时存储了针对users
属性的值的JSON字符串。
item.usersString = JSON.stringify(item.users);
Now, this would not be a perfect implementation, but it would almost always work. 现在,这不是一个完美的实现,但它几乎总是有效。 Also, if you stored this property within the browser (without storing it back to the DB), and used it to quick-search for every time user searches, I think it would be more performant that deep-searching entire array.
此外,如果您将此属性存储在浏览器中(不将其存储回数据库),并在每次用户搜索时使用它来快速搜索,我认为深度搜索整个数组会更有效。
var array = [{ category: 'Business', users: [{ name: 'Sally', tags: [{ tag: 'accounting' }, { tag: 'marketing' }] }, { name: 'Bob', tags: [{ tag: 'sales' }, { tag: 'accounting' }] } ] }, { category: 'Heritage', users: [{ name: 'Linda', tags: [{ tag: 'Italy' }, { tag: 'Macedonia' }] }, { name: 'George', tags: [{ tag: 'South Africa' }, { tag: 'Chile' }] } ] } ]; var key = "market"; // Convert the users property into a string - so that it works as a quick search target. array.forEach(function(item) { item.usersString = JSON.stringify(item.users); }); var filteredItems = array.filter(function(item) { return item.usersString.toLowerCase().indexOf(key.toLowerCase()) >= 0; }); // Delete the usersString property - if required. filteredItems.forEach(function(item) { item.usersString = undefined; // Or, // delete item.usersString; }) console.log(filteredItems);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.