带下划线或条件的下划线(下划线、lodash 或任何其他解决方案)
underscore where with or condition (underscore, lodash or any other solution)
我实现了一个 mixin 来添加 "or" 条件 _.where
var arr = [{a:1,b:4}, {a:5}, {a:6}, {a:11}];
_.mixin({
or: function(obj,arr,condition){
return _.chain(arr).where(condition).union(obj).value();
}
});
现在我可以像这样使用它了,它的工作原理有点像 sql 查询
_.chain(arr).where({a:1}).or(arr,{a:11,b:3}).or(arr,{a:2}).value();
//returns [{a:1,b:4}]
_.chain(arr).where({a:1}).or(arr,{a:11}).or(arr,{a:2}).value();
//returns [{a:1,b:4},{a:11}]
_.chain(arr).where({a:1}).or(arr,{a:11}).or(arr,{b:4}).value();
//returns [{"a":1,"b":4},{"a":11}] --no duplicates
但我想找到一种更好的方法来调用 _.or({a:1}),现在我每次都必须传递 arr _.or(arr,{a:1} ),因为链式 "or" 获得第一个对象作为先前执行函数的结果。
有没有办法在链式 mixin 函数中获取整个数组?
我希望下面 return 与我上面的实现相同的结果。 (就像一个完美的 sql 查询)
_.chain(arr).where({a:1}).or({a:11,b:3}).or({a:2}).value();//returns [{a:1,b:4}]
我的主要关注点是通过下划线来获取它,但实际上任何其他方式,如 lodash 或什至其他一些库或解决方案也可以工作。此外,我们也不需要使用链接,我也在尝试使用 compose,但到目前为止还没有成功。我想要一个在最少的线路上完美运行的解决方案。鼓励提出任何其他让它变得更好的建议。
试试这个:
// makeOr is a constructor for a 'chainable' type with: `{or, value}`
var makeOr = () => {
var fs = []
var obj = {
or: f => {
fs.push(f)
return obj
},
value: (arr) => _.chain(fs).map(f => _.where(arr, f)).union().flatten().value()
}
return obj
}
// override underscore where
// if f is our 'chainable' type we evaluate it, otherwise we default to underscore where
(function() {
where = _.where
_.mixin({
where: (arr, f) => (!!f.value && !!f.or) ? f.value(arr) : where(arr, f)
})
})();
var result = _.chain(arr)
.where(makeOr().or({a: 1}).or({a:5}).or({a:11}))
.where({a:5}).value()
我不认为扩展下划线是正确的方式,Underscore 的链接不是为此而设计的。您可以 "bend" 它,但以您想要的短小为代价。
链接的工作原理
Underscore 的链接是 "stream operation"。 chain()
将传递的对象内部存储在闭包中,return 是每个方法都绑定到该对象的 Underscore 接口。当应用过滤器函数时,结果被 returned 并在内部存储在结果对象中。 value()
调用将 return 内部引用。
自定义解决方案
您可以使用所谓的流畅界面解决此问题:
// Fluent interface to filter an array with chained, alternative conditions.
// Usage: whereOr([...]).or({...}).or({...}).end()
// whereOr([...], {...}).or({...}).end()
// Objects are _.where() conditions to subsequently apply to the array.
function whereOr(arr, condition) {
var result = [],
iface;
iface = {
or: function(subcondition) {
result = result.concat(_.where(arr, subcondition));
return iface;
},
end: function() {
return _.union(result);
}
};
if (condition) {
return iface.or(condition);
}
return iface;
}
然后你可以做
var arr = [{a:1,b:4}, {a:5}, {a:6}, {a:11}];
whereOr(arr).or({a:1}).or({a:11}).or({a:2}).end();
如果你喜欢,当然可以把这个函数混入Underscore中:
_.mixin({
whereOr: whereOr
});
工作原理
当调用 whereOr()
时,它会建立一个包含对原始 arr
的引用的作用域。它 return 是一个提供流畅函数 or()
和 end()
的对象,它们都可以访问初始数组。 end()
将 return 结果,or()
将 Userscore 的 where()
应用到内部参考并将结果添加到 result
。然后它再次 returns 接口对象。这样 or()
提供了另一种过滤的可能性,直到 end()
returns 联合结果。在此示例中,whereOr()
可选择接受第一个过滤条件作为第二个参数。
您可以将 whereOr()
与 chain()
以及 end()
与 value()
进行比较。
这是一个有趣的问题,感谢拉胡尔提醒我注意这个问题!
我想出了一个函数,它使用下划线辅助函数(尽管没有链接)解决了这个问题。它需要 2 个参数,您开始的 array
和包含您要匹配的属性的 propsObj
数组。
我实现了一个 mixin 来添加 "or" 条件 _.where
var arr = [{a:1,b:4}, {a:5}, {a:6}, {a:11}];
_.mixin({
or: function(obj,arr,condition){
return _.chain(arr).where(condition).union(obj).value();
}
});
现在我可以像这样使用它了,它的工作原理有点像 sql 查询
_.chain(arr).where({a:1}).or(arr,{a:11,b:3}).or(arr,{a:2}).value();
//returns [{a:1,b:4}]
_.chain(arr).where({a:1}).or(arr,{a:11}).or(arr,{a:2}).value();
//returns [{a:1,b:4},{a:11}]
_.chain(arr).where({a:1}).or(arr,{a:11}).or(arr,{b:4}).value();
//returns [{"a":1,"b":4},{"a":11}] --no duplicates
但我想找到一种更好的方法来调用 _.or({a:1}),现在我每次都必须传递 arr _.or(arr,{a:1} ),因为链式 "or" 获得第一个对象作为先前执行函数的结果。
有没有办法在链式 mixin 函数中获取整个数组?
我希望下面 return 与我上面的实现相同的结果。 (就像一个完美的 sql 查询)
_.chain(arr).where({a:1}).or({a:11,b:3}).or({a:2}).value();//returns [{a:1,b:4}]
我的主要关注点是通过下划线来获取它,但实际上任何其他方式,如 lodash 或什至其他一些库或解决方案也可以工作。此外,我们也不需要使用链接,我也在尝试使用 compose,但到目前为止还没有成功。我想要一个在最少的线路上完美运行的解决方案。鼓励提出任何其他让它变得更好的建议。
试试这个:
// makeOr is a constructor for a 'chainable' type with: `{or, value}`
var makeOr = () => {
var fs = []
var obj = {
or: f => {
fs.push(f)
return obj
},
value: (arr) => _.chain(fs).map(f => _.where(arr, f)).union().flatten().value()
}
return obj
}
// override underscore where
// if f is our 'chainable' type we evaluate it, otherwise we default to underscore where
(function() {
where = _.where
_.mixin({
where: (arr, f) => (!!f.value && !!f.or) ? f.value(arr) : where(arr, f)
})
})();
var result = _.chain(arr)
.where(makeOr().or({a: 1}).or({a:5}).or({a:11}))
.where({a:5}).value()
我不认为扩展下划线是正确的方式,Underscore 的链接不是为此而设计的。您可以 "bend" 它,但以您想要的短小为代价。
链接的工作原理
Underscore 的链接是 "stream operation"。 chain()
将传递的对象内部存储在闭包中,return 是每个方法都绑定到该对象的 Underscore 接口。当应用过滤器函数时,结果被 returned 并在内部存储在结果对象中。 value()
调用将 return 内部引用。
自定义解决方案
您可以使用所谓的流畅界面解决此问题:
// Fluent interface to filter an array with chained, alternative conditions.
// Usage: whereOr([...]).or({...}).or({...}).end()
// whereOr([...], {...}).or({...}).end()
// Objects are _.where() conditions to subsequently apply to the array.
function whereOr(arr, condition) {
var result = [],
iface;
iface = {
or: function(subcondition) {
result = result.concat(_.where(arr, subcondition));
return iface;
},
end: function() {
return _.union(result);
}
};
if (condition) {
return iface.or(condition);
}
return iface;
}
然后你可以做
var arr = [{a:1,b:4}, {a:5}, {a:6}, {a:11}];
whereOr(arr).or({a:1}).or({a:11}).or({a:2}).end();
如果你喜欢,当然可以把这个函数混入Underscore中:
_.mixin({
whereOr: whereOr
});
工作原理
当调用 whereOr()
时,它会建立一个包含对原始 arr
的引用的作用域。它 return 是一个提供流畅函数 or()
和 end()
的对象,它们都可以访问初始数组。 end()
将 return 结果,or()
将 Userscore 的 where()
应用到内部参考并将结果添加到 result
。然后它再次 returns 接口对象。这样 or()
提供了另一种过滤的可能性,直到 end()
returns 联合结果。在此示例中,whereOr()
可选择接受第一个过滤条件作为第二个参数。
您可以将 whereOr()
与 chain()
以及 end()
与 value()
进行比较。
这是一个有趣的问题,感谢拉胡尔提醒我注意这个问题!
我想出了一个函数,它使用下划线辅助函数(尽管没有链接)解决了这个问题。它需要 2 个参数,您开始的 array
和包含您要匹配的属性的 propsObj
数组。