I have two function that filter an array of strings. The first function filters it according to length and the other function according to the char it contains.
我有两个过滤字符串数组的函数。第一个函数根据长度过滤它,另一个函数根据它包含的char来过滤它。
The array of string is loaded on page load.
字符串数组在页面加载时加载。
How to make this functions work together, so when I filter the array according to the char it contains, and I have the appropriate strings, later on I should press the min value, and it should show me the remaining strings from the previous filter. I don't want to load the array again.
如何使这个函数一起工作,所以当我根据它包含的char过滤数组时,我有相应的字符串,稍后我应该按下最小值,它应该显示前一个过滤器的剩余字符串。我不想再次加载数组。
Here I have the first function http://jsfiddle.net/arunpjohny/03avr1vh/2/
这里我有第一个函数http://jsfiddle.net/arunpjohny/03avr1vh/2/
How to add the other and make them work together .
如何添加另一个并使它们一起工作。
Myscript:
function filter() {
var a = document.getElementById('A').checked,
e = document.getElementById('E').checked,
o = document.getElementById('O').checked,
result2; //make a copy
result2 = animals.filter(function (value) {
value = value.toLowerCase();
return (!a || value.indexOf('a') == -1) && (!e || value.indexOf('e') == -1) && (!o || value.indexOf('o') == -1);
})
document.getElementById("demo").innerHTML = result2;
}
filter();
3 个解决方案
#1
After you have a little FP lib built up for yourself, you can write your filter in a declarative way
在为自己构建了一个FP lib后,可以以声明方式编写过滤器
var animals = ["Bear", "Mouse", "Cat", "Tiger", "Lion"];
var letters = ["A", "E", "O"];
function showAnimals() {
var getSwitches = compose([
map(prop("value")),
filter(prop("checked")),
map(getElementById)
]);
var switches = getSwitches(letters);
var _filter = compose([
map(join("")),
filter(compose([
not,
any(flip(elem)(switches)),
map(toUpperCase)
])),
map(split(""))
]);
var result = _filter(animals);
getElementById("demo").innerHTML = join(", ")(result);
};
Your two main actions are:
你的两个主要行动是:
- getting the checked inputs, converting that to an array of strings.
- filtering the animals based on the checked inputs
获取已检查的输入,将其转换为字符串数组。
根据检查的输入过滤动物
Each one reads like a little story: (note to read the compose blocks in reverse).
每一个读起来都像一个小故事:(注意反向阅读组合块)。
getSwitches
- call
getElementById
on each ofletters
- filter out the unchecked inputs
- get the
value
for each input - store the resulting array as
switches
在每个字母上调用getElementById
过滤掉未经检查的输入
获取每个输入的值
将生成的数组存储为开关
_filter
- split each animal name into an array of letters
- filter each animal by
- convert animal to uppercase
- animal should not match any of
switches
将动物转换为大写
动物不应该匹配任何开关
- rejoin each animal name to a string
- store the resulting array as
result
将每个动物名称分成一组字母
通过将动物转换为大写动物来过滤每只动物不应该与任何开关相匹配
将每个动物名称重新加入字符串
将结果数组存储为结果
OK, so that's a lot of functions we used. I'm not going to go into each one in detail, but most FP libs would provide these basics for you. I go into some length detail with building some of these from scratch in this post about function composition.
好的,这就是我们使用的很多功能。我不打算详细介绍每一个,但大多数FP库都会为您提供这些基础知识。我在这篇关于功能构成的帖子中从头开始构建其中的一些,我会详细介绍一些细节。
Before we go further!
在我们走得更远之前!
"Is it performant?"
“它是高效的吗?”
Yup, but compared to what? If you write a single map
or filter
lambda, you'll likely be able to process the same information a lot faster.
是的,但相比什么?如果您编写单个映射或过滤lambda,您可能能够更快地处理相同的信息。
"So this is slow?"
“所以这很慢?”
Nope, but only you can be the judge of that. It's still going to arrive at the answer in a tiny fraction of a second, so it's plenty fast for me.
不,但只有你可以判断。它仍然会在很短的一秒钟内得出答案,所以它对我来说很快。
"Why is this better?"
“为什么这样更好?”
Well for one, it's a lot more declarative. That is, we're telling the computer what we want, and not necessarily telling it how to give us the answer. The latter is a more imperative style.
好吧,一个,它是更多的声明。也就是说,我们告诉计算机我们想要什么,而不一定告诉它如何给我们答案。后者是一种更为迫切的风格。
Things like setting variables, calling for-loops, etc, are telling the computer how to do it's job. Imperative style isn't bad, it's just it can be bad when it gets overly verbose.
像设置变量,调用for循环等等,正在告诉计算机如何完成它的工作。势在必行的风格也不错,只是当它变得过于冗长时才会变坏。
Notice we were able to solve the problem by defining two variables: switches
and result
. Everything else is just a function.
请注意,我们可以通过定义两个变量来解决问题:switch和result。其他一切都只是一个功能。
For more information, I encourage you to read the other SO answer I linked above.
有关详细信息,我建议您阅读上面链接的其他SO答案。
For those of you interested, here's the functions I used to make the above solution work
对于那些感兴趣的人,这里是我用来使上述解决方案工作的功能
var id = function(x) {
return x;
};
var getElementById = function(x) {
return document.getElementById(x);
};
var neq = function(y) {
return function(x) {
return x !== y;
};
};
var not = function(x) { return !x; };
var prop = function(x) {
return function(elem) {
return elem[x];
};
};
var indexOf = function(y) {
return function(x) {
return x.indexOf(y);
};
};
var elem = function(y) {
return compose([neq(-1), indexOf(y)]);
};
var map = function(f) {
return function(xs) {
return xs.map(f);
};
};
var filter = function(f) {
return function(xs) {
return xs.filter(f);
};
};
var any = function(f) {
return function(xs) {
return xs.some(f);
}
};
var reduceRight = function(f) {
return function(i) {
return function(xs) {
return xs.reduceRight(uncurry(f), i);
};
};
};
var toUpperCase = function(s) {
return s.toUpperCase();
};
var split = function(y) {
return function(x) {
return x.split(y);
};
};
var join = function(y) {
return function(x) {
return x.join(y);
};
};
var flip = function(f) {
return function(y) {
return function(x) {
return f(x)(y);
};
};
};
var uncurry = function(f) {
return function(x, y) {
return f(x)(y);
};
};
var compose = flip(reduceRight(flip(id)));
And that's all, Folks!
这就是全部,伙计们!
#2
You can chain the length filter after the letter filter:
您可以在字母过滤器后链接长度过滤器:
result2 = animals.filter(function (value) {
// letter filter
}).filter(function (value) {
// length filter
});
快速样本。
#3
or you can use some functional programming and do a curry of two functions like this:
或者您可以使用一些函数式编程并执行两个函数的咖喱:
function compose(f1, f2)
{
return function(val) {
return f1(val)&&f2(val);
}
}
// in this case the .filter traverses the array only once,
// instead of twice, i.e once for each subfilter function
result2 = animals.filter(compose(letterFilter, lengthFilter));
UPDATE if in understand correctly and you need to filter again (by another filter) at a later time, you will need to store the intermediate results from previous filter and use these as input to the other filter, or just filter the whole array again with a composed filter (as in this example).
更新如果正确理解并且您需要稍后再次过滤(通过另一个过滤器),则需要存储前一过滤器的中间结果并将其用作另一个过滤器的输入,或者仅使用过滤器重新过滤整个数组组合过滤器(如本例所示)。
The best approach depends on the size of the array and code modularity and independence you would like to achieve.
最好的方法取决于数组的大小和代码模块性以及您希望实现的独立性。
#1
After you have a little FP lib built up for yourself, you can write your filter in a declarative way
在为自己构建了一个FP lib后,可以以声明方式编写过滤器
var animals = ["Bear", "Mouse", "Cat", "Tiger", "Lion"];
var letters = ["A", "E", "O"];
function showAnimals() {
var getSwitches = compose([
map(prop("value")),
filter(prop("checked")),
map(getElementById)
]);
var switches = getSwitches(letters);
var _filter = compose([
map(join("")),
filter(compose([
not,
any(flip(elem)(switches)),
map(toUpperCase)
])),
map(split(""))
]);
var result = _filter(animals);
getElementById("demo").innerHTML = join(", ")(result);
};
Your two main actions are:
你的两个主要行动是:
- getting the checked inputs, converting that to an array of strings.
- filtering the animals based on the checked inputs
获取已检查的输入,将其转换为字符串数组。
根据检查的输入过滤动物
Each one reads like a little story: (note to read the compose blocks in reverse).
每一个读起来都像一个小故事:(注意反向阅读组合块)。
getSwitches
- call
getElementById
on each ofletters
- filter out the unchecked inputs
- get the
value
for each input - store the resulting array as
switches
在每个字母上调用getElementById
过滤掉未经检查的输入
获取每个输入的值
将生成的数组存储为开关
_filter
- split each animal name into an array of letters
- filter each animal by
- convert animal to uppercase
- animal should not match any of
switches
将动物转换为大写
动物不应该匹配任何开关
- rejoin each animal name to a string
- store the resulting array as
result
将每个动物名称分成一组字母
通过将动物转换为大写动物来过滤每只动物不应该与任何开关相匹配
将每个动物名称重新加入字符串
将结果数组存储为结果
OK, so that's a lot of functions we used. I'm not going to go into each one in detail, but most FP libs would provide these basics for you. I go into some length detail with building some of these from scratch in this post about function composition.
好的,这就是我们使用的很多功能。我不打算详细介绍每一个,但大多数FP库都会为您提供这些基础知识。我在这篇关于功能构成的帖子中从头开始构建其中的一些,我会详细介绍一些细节。
Before we go further!
在我们走得更远之前!
"Is it performant?"
“它是高效的吗?”
Yup, but compared to what? If you write a single map
or filter
lambda, you'll likely be able to process the same information a lot faster.
是的,但相比什么?如果您编写单个映射或过滤lambda,您可能能够更快地处理相同的信息。
"So this is slow?"
“所以这很慢?”
Nope, but only you can be the judge of that. It's still going to arrive at the answer in a tiny fraction of a second, so it's plenty fast for me.
不,但只有你可以判断。它仍然会在很短的一秒钟内得出答案,所以它对我来说很快。
"Why is this better?"
“为什么这样更好?”
Well for one, it's a lot more declarative. That is, we're telling the computer what we want, and not necessarily telling it how to give us the answer. The latter is a more imperative style.
好吧,一个,它是更多的声明。也就是说,我们告诉计算机我们想要什么,而不一定告诉它如何给我们答案。后者是一种更为迫切的风格。
Things like setting variables, calling for-loops, etc, are telling the computer how to do it's job. Imperative style isn't bad, it's just it can be bad when it gets overly verbose.
像设置变量,调用for循环等等,正在告诉计算机如何完成它的工作。势在必行的风格也不错,只是当它变得过于冗长时才会变坏。
Notice we were able to solve the problem by defining two variables: switches
and result
. Everything else is just a function.
请注意,我们可以通过定义两个变量来解决问题:switch和result。其他一切都只是一个功能。
For more information, I encourage you to read the other SO answer I linked above.
有关详细信息,我建议您阅读上面链接的其他SO答案。
For those of you interested, here's the functions I used to make the above solution work
对于那些感兴趣的人,这里是我用来使上述解决方案工作的功能
var id = function(x) {
return x;
};
var getElementById = function(x) {
return document.getElementById(x);
};
var neq = function(y) {
return function(x) {
return x !== y;
};
};
var not = function(x) { return !x; };
var prop = function(x) {
return function(elem) {
return elem[x];
};
};
var indexOf = function(y) {
return function(x) {
return x.indexOf(y);
};
};
var elem = function(y) {
return compose([neq(-1), indexOf(y)]);
};
var map = function(f) {
return function(xs) {
return xs.map(f);
};
};
var filter = function(f) {
return function(xs) {
return xs.filter(f);
};
};
var any = function(f) {
return function(xs) {
return xs.some(f);
}
};
var reduceRight = function(f) {
return function(i) {
return function(xs) {
return xs.reduceRight(uncurry(f), i);
};
};
};
var toUpperCase = function(s) {
return s.toUpperCase();
};
var split = function(y) {
return function(x) {
return x.split(y);
};
};
var join = function(y) {
return function(x) {
return x.join(y);
};
};
var flip = function(f) {
return function(y) {
return function(x) {
return f(x)(y);
};
};
};
var uncurry = function(f) {
return function(x, y) {
return f(x)(y);
};
};
var compose = flip(reduceRight(flip(id)));
And that's all, Folks!
这就是全部,伙计们!
#2
You can chain the length filter after the letter filter:
您可以在字母过滤器后链接长度过滤器:
result2 = animals.filter(function (value) {
// letter filter
}).filter(function (value) {
// length filter
});
快速样本。
#3
or you can use some functional programming and do a curry of two functions like this:
或者您可以使用一些函数式编程并执行两个函数的咖喱:
function compose(f1, f2)
{
return function(val) {
return f1(val)&&f2(val);
}
}
// in this case the .filter traverses the array only once,
// instead of twice, i.e once for each subfilter function
result2 = animals.filter(compose(letterFilter, lengthFilter));
UPDATE if in understand correctly and you need to filter again (by another filter) at a later time, you will need to store the intermediate results from previous filter and use these as input to the other filter, or just filter the whole array again with a composed filter (as in this example).
更新如果正确理解并且您需要稍后再次过滤(通过另一个过滤器),则需要存储前一过滤器的中间结果并将其用作另一个过滤器的输入,或者仅使用过滤器重新过滤整个数组组合过滤器(如本例所示)。
The best approach depends on the size of the array and code modularity and independence you would like to achieve.
最好的方法取决于数组的大小和代码模块性以及您希望实现的独立性。