javascript Underscore.js findWhere 嵌套对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17578725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Underscore.js findWhere nested objects
提问by wesbos
I have an object of folders/files that looks like this:
我有一个文件夹/文件对象,如下所示:
{
about.html : {
path : './about.html'
},
about2.html : {
path : './about2.html'
},
about3.html : {
path : './about3.html'
},
folderName : {
path : './folderName',
children : {
sub-child.html : {
path : 'folderName/sub-child.html'
}
}
}
}
And it can go 6-7 levels deep of folders having children.
它可以深入到有孩子的文件夹的 6-7 层。
I want to find the object where pathis equal to a string that I provide. Regardless of how deep it is.
我想找到路径等于我提供的字符串的对象。不管它有多深。
I'm using underscore which only does top level:
我正在使用只做顶级的下划线:
_.findWhere(files,{path:'./about2.html'}
How can I do a deep, nested search. Does underscore have something for this or do I need to build a mixin with recursion?
如何进行深入的嵌套搜索。下划线是否有此用途,或者我是否需要使用递归构建混合?
回答by dariusriggins
This isn't the prettiest code, but I tested it out and it seems to work the way you are asking. It's setup as a lodash/underscore mixin, but can be used however. Usage would be like this:
这不是最漂亮的代码,但我对其进行了测试,它似乎按照您的要求工作。它被设置为 lodash/underscore mixin,但可以使用。用法如下:
_.findDeep(testItem, { 'path': 'folderName/sub-child.html' })
Implementation:
执行:
findDeep: function(items, attrs) {
function match(value) {
for (var key in attrs) {
if(!_.isUndefined(value)) {
if (attrs[key] !== value[key]) {
return false;
}
}
}
return true;
}
function traverse(value) {
var result;
_.forEach(value, function (val) {
if (match(val)) {
result = val;
return false;
}
if (_.isObject(val) || _.isArray(val)) {
result = traverse(val);
}
if (result) {
return false;
}
});
return result;
}
return traverse(items);
}
回答by McGarnagle
Instead of findWhere
, use filter
, which takes a function as the predicate rather than a key-value map. Use a recursive function to check the current node and possible children. Something like this:
而不是findWhere
,使用filter
,它将函数作为谓词而不是键值映射。使用递归函数检查当前节点和可能的子节点。像这样的东西:
var searchText = './about2.html';
var recursiveFilter = function(x) {
return x.path == searchText ||
( typeof x.children != 'undefined' && recursiveFilter(x.children['sub-child.html']) );
};
_.filter(files, recursiveFilter);
Edit
编辑
Assuming this works, you'll probably want to make a function getRecursiveFilter(searchText)
. Here's how that would look:
假设这有效,您可能想要创建一个 function getRecursiveFilter(searchText)
。这是它的样子:
function getRecursiveFilter(searchText) {
var recursiveFilter = function(x) {
return x.path == searchText ||
(typeof x.children != 'undefined'
&& arguments.callee(x.children['sub-child.html']) );
};
return recursiveFilter;
}
Note that here, recursiveFilter
uses arguments.callee
to call itself recursively.
注意这里,recursiveFilter
用于arguments.callee
递归调用自身。
回答by abenrob
This already has an accepted answer, but this other answer was very clean and perfect for my similar situation: https://stackoverflow.com/a/21600748/1913975_.filter
+_.where
这已经有一个可以接受的答案,但另一个答案对于我的类似情况非常干净和完美:https: //stackoverflow.com/a/21600748/1913975_.filter
+_.where
回答by adhiroha
Though accepted answer works, it's too generic - it searches all the properties of an object to find children. I am proposing introducing an extra parameter, called 'recursProperty' which will be considered to go deep in the object. This solution is also setup to be used as lodash/underscore mixin and extends loadash/underscore capabilities.
尽管接受的答案有效,但它太通用了 - 它搜索对象的所有属性以查找子项。我提议引入一个名为“recursProperty”的额外参数,它将被视为深入对象。此解决方案还设置为用作 lodash/underscore mixin 并扩展 loadash/underscore 功能。
_.findDeep = function(collection, predicate, recursProperty){
let items = [];
_.each(collection, each => items.push(each));
return _.find(items, function(value, key, coll){
if (predicate(value, key, coll)){
return true;
} else {
_.each(value[recursProperty], each => items.push(each));
}
});
};
It can be used as any other underscore function. e.g,
它可以用作任何其他下划线函数。例如,
_.findDeep(self.baseEntities, baseEntity => baseEntity.id === 71, 'entity');
Not providing proper value for 'recursProperty' argument or providing null/undefined will simply make the search only on first level (no going deep).
不为 'recursProperty' 参数提供适当的值或提供 null/undefined 只会使搜索仅在第一级(不会深入)。