使用谓词和两个函数映射集合 [英] Map a collection using a predicate and two functions
问题描述
在尝试以函数式风格编写代码时,我经常遇到要使用两个函数将一个集合或流映射到另一个集合或流的情况:一个函数应用于传递给定谓词的元素,另一个函数应用于传递给定谓词的元素失败.这两个函数都产生一个公共输出,应将其收集起来以进行进一步处理.
While trying to write code in a functional style, I often encounter the scenario where I want to map one collection or stream to another using two functions: one function applied to elements that pass a given predicate and another function applied to elements that fail. Both functions produce a common output, which should be collected for further processing.
这是Java中人为的示例.
Here is a contrived example in Java.
Stream.of("foo", "bar", "baz", "qux")
.map(it -> it.startsWith("ba") ? it.toUpperCase() : new StringBuilder(it).reverse())
.forEach(System.out::println);
和Groovy中的相同示例.
And the same example in Groovy.
["foo", "bar", "baz", "qux"]
.collect{ it.startsWith("ba") ? it.toUpperCase() : it.reverse() }
.each{ println(it) }
我的问题是关于用于实现此映射的条件(三元)语句.是否有功能上的惯用法来实现这种映射而无需求助于分支逻辑?
My question is regarding the conditional (ternary) statement used to implement this mapping. Is there a functional idiom to implement such a mapping without resorting to branching logic?
推荐答案
您始终可以使用另一个函数对表达式进行抽象.由于您标记了问题与语言无关,因此,我使用可在您喜欢的浏览器中执行的Javascript编码示例-希望可以:
You can always abstract over an expression with another function. Since you tagged your question language-agnostic, I encode my example with Javascript, executable in your favorite browser - I hope this is okay:
// select :: (a -> Boolean, a -> b, a -> b) -> a -> b
const select = (p, f, g) => x => p(x) ? f(x) : g(x);
// mapSelect :: (a -> Boolean, a -> b, a -> b) -> [a] -> [b]
const mapSelect = (p, f, g) => xs => xs.map(select(p, f, g));
const reverse = s => s.split("").reverse().join("");
const toUpperCase = s => s.toUpperCase();
const startsWith = s => t => t.indexOf(s) === 0
const xs = ["foo", "bar", "baz", "qux"];
console.log(
mapSelect(startsWith("ba"), toUpperCase, reverse) (xs)
);
很显然, mapSelect
不能将您从条件运算符中解救出来.这只是抽象的另一层.由于它不如 map
常见,因此您会特别增加同事的认知负担而不会增加很多负担.
Obviously, mapSelect
doesn't save you from the conditional operator. It is just another layer of abstraction. Since it is not as common as map
, you increase especially the cognitive load of your coworkers without getting much.
结论:我会坚持使用显式条件运算符,而不是伪装分支逻辑.
Conclusion: I would stick with the explicit conditional operator instead of disguising the branching logic.
这篇关于使用谓词和两个函数映射集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!