我一直在尝试创建一个通用的分区函数,它可以返回一个数组的数组,该函数的制作应该遵循以下准则。Arguments:
目标:调用<函数>对<数组>中的每个元素进行调用。
对<array>中的每个元素调用<函数>,并将参数传递给它。
element, key, <array>
返回一个由2个子数组组成的数组。
0. 一个包含所有值的数组,其中<function>返回的是真值 1.一个包含所有值的数组,其中<function>返回的是假值。
这是我目前的情况。我得到的回报是两个。我觉得也许我只需要在两个不同的场合进行过滤功能,但我不知道如何将它放在一起。非常感谢大家的想法和建议。
_.partition = function (collection, test){
var allValues = [];
var matches = [];
var misMatches = [];
_.filter(collection.value, function(value, key, collection){
if (test(value[key], key, collection) === "string"){
matches.push(value[key]);
}else{
misMatches.push(value[key]);
}
});
return allValues.push(matches, misMatches);
}
下面是一个版本,它使用 reduce
:
function partition(arr, filter) {
return arr.reduce(
(r, e, i, a) => {
r[filter(e, i, a) ? 0 : 1].push(e);
return r;
}, [[], []]);
}
这里有一个替代版本,使用 Array#filter
来寻找匹配的对象,并随着时间的推移建立一个非匹配对象的数组。
function partition(arr, filter) {
var fail = [];
var pass = arr.filter((e, i, a) => {
if (filter(e, i, a)) return true;
fail.push(e);
});
return [pass, fail];
}
你说的没错 filter
分别在不同的场合采用这种方法。一 filter
调用将获得真值;另一个将获得假值。
_.partition = function(collection, testFunc) {
var matches = collection.filter(function(elem) {
return test(elem) === 'string';
});
var misMatches = collection.filter(function(elem) {
return test(elem) !== 'string';
});
return [matches, misMatches];
}
你已经很接近了,但我发现有几个问题。
allValues.push
也就是 不 allValues
本身,而是数组的新长度。_.filter
来迭代数组元素,并将它们排序为两个数组。这很奇怪,因为这并不是 _.filter
.如果你想要一个快速和可读的解决方案,使用 _.filter
这样就可以了。
_.mixin({
partition: function(collection, test) {
return [
_.filter(collection, test), // items which satisfy condition
_.filter(collection, _.negate(test)) // items which don't
];
}
});
下面是一个更有效的解决方案,它只需要在集合上做一次传递(这几乎是你已经有的)。
_.mixin({
partition: function(collection, test) {
var matches = [], misMatches = [], value;
// can replace this loop with _.each
for (var i = 0, len = collection.length; i < len; ++i) {
value = collection[i];
// push the value into the appropriate array
if (test(value, i, collection)) {
matches.push(value);
} else {
misMatches.push(value);
}
}
return [matches, misMatches];
}
});
使用示例(和 灌篮机):
function isOdd(x) {
return x % 2;
}
// _.mixin allows you to do either one of these
_.partition([1, 2, 3, 4, 5, 6], isOdd); // result: [[1, 3, 5], [2, 4, 6]]
_([1, 2, 3, 4, 5, 6]).partition(isOdd); // result: [[1, 3, 5], [2, 4, 6]]
// this is a use case you brought up in the comments
_.partition([1, "a", 2, "b", 3, "c"], _.isString); // result: [["a", "b", "c"], [1, 2, 3]]
这通常被称为 partition
在函数式语言中。你用一个数组(xs
)和一个谓词函数(p
)到a reduce
初始值的函数 [[],[]]
.
var partition = (xs,p) => xs.reduce( (r,e) => ( p(e) ? r[0].push(e)
: r[1].push(e)
, r
)
, [[],[]]
);
这样:
> partition([1,2,3,4,5,6,7,8,9,0], x => x < 5)
> [[1, 2, 3, 4, 0],[5, 6, 7, 8, 9]]