【发布时间】:2021-12-26 22:45:36
【问题描述】:
我正在尝试了解有关函数式编程的更多信息。我做了一些训练视频,我想我会做一个 Kata。
也许我只是选了一个不好的,我试图用谓词来做过滤,但它似乎添加了比看起来需要的更多的代码。我相信有更好的方法。
谢谢!
卡塔 --------
n: 2
oldValue: 'a'
newValue: 'o'
"Vader said: No, I am your father!" -> "Vader soid: No, I am your fother!"
1 2 3 4 -> 2nd and 4th occurence are replaced
package kata;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
public class ReplaceEveryNth {
public static Integer interPos = 0;
//works but isn't great. How do you make this functional?
public static String replaceNth(String text, Integer n, Character oldValue, Character newValue){
//String builder allows for the setCharAt Function to swap char
StringBuilder sb = new StringBuilder(text);
//make an array of all the positions the char is found at.
ArrayList<Integer> foundAt = new ArrayList<>();
sb.toString().chars().forEach( c -> {
interPos++;
if (c == oldValue) foundAt.add(interPos);
});
//need to for mod div
AtomicInteger index = new AtomicInteger();
index.set(1);
//if mod this pos is 0, then swap it.
foundAt.forEach(pos -> {
System.out.println("pos Mods: " + pos + " " + index);
if (index.get() % n == 0) {
sb.setCharAt(pos-1, newValue);
}
index.getAndIncrement();
});
return sb.toString();
}
}
编辑这个更新的方法,它不是真的有用吗?但它使用单个循环。
public static String replaceNth(String text, Integer n, Character oldValue, Character newValue){
char[] chars = text.toCharArray();
char[] ret = new char[chars.length];
int counter = 1;
for (int i = 0; i < chars.length; ++i)
{
ret[i] = chars[i];
if (chars[i] == oldValue) {
if (counter % n == 0) {
ret[i] = newValue;
counter = 0;
}
counter++;
}
}
return new String(ret);
}
【问题讨论】:
-
为什么要保留索引?您可以将它们替换为找到的,这样您只需要一个流。
-
没有其他原因......原来我做了2个谓词...... static BiPredicate
shouldReplace = (pos, lastFound) -> { if ((lastFound + pos) = = interPos) { System.out.println("FOUND"); } 返回真; };静态 BiPredicate foundReplaceChar = (c, oldValue) -> c.equals(oldValue);并尝试使用一个循环,但它并没有使任何东西更容易阅读或不那么复杂。但是,我可能只是做的不好。 -
我曾希望尝试做出类似的东西:return Stream.doSomething(predicate).dosomethingelse(whatever);
-
你不能用谓词过滤你的字符流,因为你甚至需要不等于旧值的字符才能在结果字符串中结束。要替换字符,您可以
.map()每个字符都使用一元运算,这是某种“基于函数”的解决方案。 -
你接近它的方式不是很实用。一个迹象是您正在使用可变数据 (StringBuilder)。一种“更实用”的方法是 1. 按 oldValue ("a") 拆分字符串,2. 创建一系列分隔符('a'、'o'、'a'、'o' 等),最后 3. 然后将这些片段再次连接在一起,将分割值与序列交替。上面的每一步都可以是它自己的函数(可能是已经给定的,比如 String.split)
标签: java functional-programming