我有一个嵌套的JSON,我想使用lodash进行搜索。如果我正在寻找的搜索词位于某些键内,并且其中一个键是动态的,我如何从data
获取根对象?
例如,如果我有:
"data": [
{
"name": "Bob's concourse"
"activities": [
{
"day": "Monday",
"routines":
{
"Biking":
{
"details": "won 3 trophies"
"type": "road"
},
"Kayaking":
{
"details": "participated in 3 races"
"type": "rhythm"
}
}
}
}
]
},
{..other_data_etc...},
]
activities
可以是[]
;它不能保证它包含任何数据。routines
键是动态的。即,Biking
,Kayaking
是动态字符串。它可以是任何东西。如果我想搜索races
(不区分大小写),我想专门搜索:
data.name
data.activities.routines.*
(动态键)data.activities.routines.*.details
如果其中任何一个匹配,那么它将返回根对象:{ "name": "Bob", ..... }
我能够让name
返回:
function searchText(collection, searchterm) {
return _.filter(collection, function(o) {
return _.includes(o.name.toLowerCase(), searchterm)
} );
};
但我仍然是lodash的新手,我无法让任何嵌套搜索正确返回,尤其是动态键部分。
有人可以帮忙解释一下解决方案吗?
答案 0 :(得分:0)
使用lodash扩展您现有的尝试:
const obj = {
data: [{
name: 'Bob\'s concourse',
activities: [{
day: 'Monday',
routines: {
Biking: {
details: 'won 3 trophies',
type: 'road'
},
Kayaking: {
details: 'participated in 3 races',
type: 'rhythm'
}
}
}]
}]
};
function search(str, data) {
const searchStr = str.toLowerCase();
// Only return the entries that contain a matched value
return _.filter(data, (datum) => {
// Check if name matches
return _.includes(datum.name, searchStr)
|| _.some(datum.activities, (activity) => {
return _.entries(activity.routines).some(([routine, {details}]) => {
// Check if dynamic routine matches or details
return _.includes(routine, searchStr) || _.includes(details, searchStr);
});
});
});
}
console.log(search('foobar', obj.data));
console.log(search('races', obj.data));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
您也可以使用纯JavaScript实现此目的。使用一些新的语法(如destructuring assignment)和新的本机方法(如Object.entries
)基本上遵循与使用lodash相同的模式:
const obj = {
data: [{
name: 'Bob\'s concourse',
activities: [{
day: 'Monday',
routines: {
Biking: {
details: 'won 3 trophies',
type: 'road'
},
Kayaking: {
details: 'participated in 3 races',
type: 'rhythm'
}
}
}]
}]
};
function search(str, data) {
const regex = RegExp(str, 'i');
// Only return the entries that contain a matched value
return data.filter((datum) => {
// Check if name matches
return regex.test(datum.name)
|| datum.activities.some((activity) => {
return Object.entries(activity.routines).some(([routine, {details}]) => {
// Check if dynamic routine matches or details
return regex.test(routine) || regex.test(details);
});
});
});
}
console.log(search('foobar', obj.data));
console.log(search('races', obj.data));