如何通过JavaScript对象支持globstar风格的**
搜索?
这就像lodash的_.get
一样,只是要查询的对象可以包含这些特殊的*
和**
属性,如果没有完全匹配则会匹配这些属性
在下面的示例代码中,{ **: { middleName: 3 }}
规则应与以下路径匹配:
['middleName']
['clients', 'middleName']
['clients', '0', 'middleName']
由于**
匹配0个或更多元素,因此{**: { middleName: x }}
基本上匹配任何以'middleName'
结尾的数组并返回x
。
但是,由于还一个*
规则,它只匹配一个级别(恰好是1个具有任何值的元素),因此应该优先于{{ 1}},导致第二条路径评估为**
。
在实践中,我不太关心优先权,因为我不应该写重叠"规则",但我无法弄清楚如何实施{{ 1}}无论如何。
如果你需要一个更实际的例子,我打算用它来做的是:1,2,3号码将被验证器功能和"路径"取代。将是{ lastName: 2 }
个名字。通过这种方式,我可以为表单指定验证规则。
另外,我真的只想返回叶子节点,所以其中一个返回**
的事实有点奇怪,但它是一个边缘情况我不太关心。如果<input>
优先于此,因为它是叶子节点匹配,我想这会更好。
代码:
{ lastName: 2 }
&#13;
答案 0 :(得分:2)
问题似乎很像文件路径通配。代码中的规则对象似乎有点奇怪。不确定你是如何结束它或它的更广泛的目的可能但是......我认为你可以将你的规则从一个对象重构为glob路径。有很多JS包用于globbing。以下是使用minimatch globber的重构(在原始列表中添加规则以显示如何使用glob表达式减少冗余)。
var minimatch = require("minimatch")
var _ = require('underscore')
rules = {
'firstName': 1,
'clients/*/lastName': 2,
'**/middleName': 3,
'people/*/+(middleName|lastName)': 4,
}
rule_keys = _.keys(rules).sort().reverse() // Force a well defined match order.
function glob(rules, path) {
path = path.join('/')
for(r of rule_keys) {
if(minimatch(path, r)) {
return rules[r];
}
}
}
paths = [
[['firstName'], "1"],
[['clients', '0', 'lastName'], "2"],
[['clients', '0', 'middleName'], "should be 3"],
[['clients', 'middleName'], "should be 2|3"],
[['middleName'], "should be 3"],
[['people', '0', 'middleName'], "should be 4"],
];
for(p in paths) {
console.log(glob(rules, paths[p][0]), paths[p][1]);
}
实际上,minimatch实现可能会将字符串表达式解释为类似于您所显示的对象 - 除了更复杂,因为它支持更多功能。