I have a function that returns the filtered result based on string in the object (if it exist or not)
我有一个函数,它根据对象中的字符串返回经过过滤的结果(如果它存在或不存在)
let foo = nodes.reduce((arr, cur) => {
cur.classes.split(' ').filter((el) => {
if (el === 'foo') arr.push(cur)
})
return arr;
}, []);
So it's just return all objects in array that contains 'foo' in classes object This one, for example:
它返回数组中包含foo的所有对象比如这个
let nodes = [
{node: 'h1', classes: 'foo'},
{node: 'p', classes: 'bar'},
{node: 'p', classes: 'baz xxx'},
{node: 'h2', classes: 'bar baz foo'},
{node: 'ul', classes: 'poop foo'}
]
But my guts tells that the function possible to write more easily and succinctly. Any ideas?
但我的直觉告诉我,这个函数可以写得更容易、更简洁。什么好主意吗?
3 个解决方案
#1
4
You could use just Array#filter
.
您可以使用数组#过滤器。
let nodes = [{node: 'h1', classes: 'foo'}, {node: 'p', classes: 'bar'}, {node: 'p', classes: 'baz xxx'}, {node: 'h2', classes: 'bar baz foo'}, {node: 'ul', classes: 'poop foo'}],
foo = nodes.filter(a => a.classes.split(' ').some(b => b === 'foo'));
console.log(foo);
#2
1
Per usual, @NinaScholz offers a great, straightforward approach. You'd be well-off following her advice.
通常,@NinaScholz提供了一个非常简单的方法。听了她的建议,你会很富裕的。
I personally like to dissect these problem a little further and demonstrate how smaller, reusable functions can be combined to achieve the desired effect. It's my hope that this answer will help you see that functional programming in JavaScript easily extends beyond the built-in prototypal methods.
我个人喜欢更深入地剖析这些问题,并演示如何将更小的、可重用的函数组合在一起以达到预期的效果。我希望这个答案能帮助您看到JavaScript中的函数式编程很容易扩展到内置原型方法之外。
Comments help you understand types but are completely optional.
注释帮助您理解类型,但完全是可选的。
// comp :: (b -> c) -> (a -> b) -> (a -> c)
const comp = f => g => x => f (g (x));
// filter :: (a -> Boolean) -> [a] -> [a]
const filter = f => xs => xs.filter(f);
// some :: (a -> Boolean) -> [a] -> Boolean
const some = f => xs => xs.some(f);
// eq :: (String a, Number a) => a -> a -> Boolean
const eq = x => y => y === x;
// nodeClasses :: Node -> [String]
const nodeClasses = ({classes}) => classes.split(' ');
// nodesWithClass :: String -> [Node] -> [Node]
const nodesWithClass = c => filter (comp (some (eq (c))) (nodeClasses));
// nodes :: [Node]
let nodes = [
{node: 'h1', classes: 'foo'},
{node: 'p', classes: 'bar'},
{node: 'p', classes: 'baz xxx'},
{node: 'h2', classes: 'bar baz foo'},
{node: 'ul', classes: 'poop foo'}
];
console.log(nodesWithClass('foo') (nodes));
#3
0
As an alternative to "filter some", as shown by Nina, a slightly different approach.
作为“过滤一些”的替代方案,正如尼娜所示,是一种略有不同的方法。
Doesn't look that clean, but is more performant (as far as performance matters at such a simple task).
看起来没那么干净,但更高效(就性能而言,在这么简单的任务中很重要)。
let nodes = [
{node: 'h1', classes: 'foo'},
{node: 'p', classes: 'bar'},
{node: 'p', classes: 'foo-bar'},
{node: 'p', classes: 'baz xxx'},
{node: 'h2', classes: 'bar baz foo'},
{node: 'ul', classes: 'poop foo'}
];
let foo = nodes.filter(node => (' ' + node.classes + ' ').contains(' foo '));
#1
4
You could use just Array#filter
.
您可以使用数组#过滤器。
let nodes = [{node: 'h1', classes: 'foo'}, {node: 'p', classes: 'bar'}, {node: 'p', classes: 'baz xxx'}, {node: 'h2', classes: 'bar baz foo'}, {node: 'ul', classes: 'poop foo'}],
foo = nodes.filter(a => a.classes.split(' ').some(b => b === 'foo'));
console.log(foo);
#2
1
Per usual, @NinaScholz offers a great, straightforward approach. You'd be well-off following her advice.
通常,@NinaScholz提供了一个非常简单的方法。听了她的建议,你会很富裕的。
I personally like to dissect these problem a little further and demonstrate how smaller, reusable functions can be combined to achieve the desired effect. It's my hope that this answer will help you see that functional programming in JavaScript easily extends beyond the built-in prototypal methods.
我个人喜欢更深入地剖析这些问题,并演示如何将更小的、可重用的函数组合在一起以达到预期的效果。我希望这个答案能帮助您看到JavaScript中的函数式编程很容易扩展到内置原型方法之外。
Comments help you understand types but are completely optional.
注释帮助您理解类型,但完全是可选的。
// comp :: (b -> c) -> (a -> b) -> (a -> c)
const comp = f => g => x => f (g (x));
// filter :: (a -> Boolean) -> [a] -> [a]
const filter = f => xs => xs.filter(f);
// some :: (a -> Boolean) -> [a] -> Boolean
const some = f => xs => xs.some(f);
// eq :: (String a, Number a) => a -> a -> Boolean
const eq = x => y => y === x;
// nodeClasses :: Node -> [String]
const nodeClasses = ({classes}) => classes.split(' ');
// nodesWithClass :: String -> [Node] -> [Node]
const nodesWithClass = c => filter (comp (some (eq (c))) (nodeClasses));
// nodes :: [Node]
let nodes = [
{node: 'h1', classes: 'foo'},
{node: 'p', classes: 'bar'},
{node: 'p', classes: 'baz xxx'},
{node: 'h2', classes: 'bar baz foo'},
{node: 'ul', classes: 'poop foo'}
];
console.log(nodesWithClass('foo') (nodes));
#3
0
As an alternative to "filter some", as shown by Nina, a slightly different approach.
作为“过滤一些”的替代方案,正如尼娜所示,是一种略有不同的方法。
Doesn't look that clean, but is more performant (as far as performance matters at such a simple task).
看起来没那么干净,但更高效(就性能而言,在这么简单的任务中很重要)。
let nodes = [
{node: 'h1', classes: 'foo'},
{node: 'p', classes: 'bar'},
{node: 'p', classes: 'foo-bar'},
{node: 'p', classes: 'baz xxx'},
{node: 'h2', classes: 'bar baz foo'},
{node: 'ul', classes: 'poop foo'}
];
let foo = nodes.filter(node => (' ' + node.classes + ' ').contains(' foo '));