gpt4 book ai didi

javascript - 如何为对象实现 glob **?

转载 作者:行者123 更新时间:2023-11-29 21:11:40 27 4
gpt4 key购买 nike

我如何支持 globstar 风格 **搜索 JavaScript 对象?

这就像 lodash 的 _.get 除了要查询的对象可以包含这些特殊的 ***如果没有完全匹配,将匹配的属性。

在下面的示例代码中,{ **: { middleName: 3 }}规则应匹配以下路径:

['middleName']
['clients', 'middleName']
['clients', '0', 'middleName']

因为 **匹配 0 个或多个元素,所以 {**: { middleName: x }}本质上匹配任何以 'middleName' 结尾的数组并返回 x .

但是,由于还有一个*规则,它只匹配一个级别(恰好 1 个元素具有任何值),应该优先于 ** ,导致第二条路径评估为 { lastName: 2 }相反。

在实践中,我不太关心优先级,因为不应该写重叠的“规则”,但我不知道如何实现 **无论如何。

如果你需要一个更实际的例子,我打算用它来做的是:1、2、3 数字将被验证器函数替换,“路径”将是 <input>名字。通过这种方式,我可以为我的表单指定验证规则。

此外,我真的只想返回叶节点,所以其中一个返回 { lastName: 2 } 的事实有点奇怪,但这是我不太关心的边缘情况。如果**优先于此,因为它是叶节点匹配,我想那会更好。

代码:

function glob(object, path, defaultValue) {
let [first, ...rest] = path;
let value = object[first];
if (value === undefined) {
value = object['*'];
if (value === undefined) {
// TODO: support **
return defaultValue;
}
}
if (rest.length) {
return glob(value, rest, defaultValue);
}
return value;
}

let rules = {
firstName: 1, // matches ['firstName']
clients: {
'*': {
lastName: 2, // matches ['clients', anything, 'lastName']
}
},
'**': {
middleName: 3, // matches [...anything, 'middleName']
}
}

console.log(glob(rules, ['firstName'])); // 1
console.log(glob(rules, ['clients', '0', 'lastName'])); // 2
console.log(glob(rules, ['clients', '0', 'middleName'])); // should be 3
console.log(glob(rules, ['clients', 'middleName'])); // should be { lastName: 2 } or 3, whatever's easier to implement
console.log(glob(rules, ['middleName'])); // should be 3

最佳答案

问题看起来很像文件路径通配。您代码中的规则对象似乎有点奇怪。不确定你是如何结束它的或者它的更广泛的目的可能是什么但是......我认为你可以将你的规则从一个对象重构为全局路径。有很多 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]);
}

事实上,最小匹配实现可能会将字符串表达式解释为一个与您所展示的对象类似的对象 - 除了更复杂,因为它支持更多功能。

关于javascript - 如何为对象实现 glob **?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41559276/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com