gpt4 book ai didi

java - 如何使用流将此程序转换为 Java 8 函数式风格?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:31:58 25 4
gpt4 key购买 nike

问题
我编写了一个程序来找出给定字符串的字符大写和小写的所有可能性。

例如,输入 - “ab”/“Ab”等 - 其中任何一个输出 - ["ab","Ab","aB","AB"]

代码

算法不正确 - 请检查下方。

public static ArrayList<String> permuteUCLC(String a)
{

String s=new String(a.toLowerCase());
ArrayList<String> arr = new ArrayList<>();
arr.add(a);
int l = a.length();
for(int i=0;i<=l;i++)
{
for(int j=i+1;j<=l;j++)
{
arr.add(s.substring(0,i)+s.substring(i,j).toUpperCase()+s.substring(j,l));
}
}
Collections.sort(arr);
Collections.reverse(arr);
return arr;
}

注意
问完问题我才意识到我的算法是错误的。我会尝试并在适当的时候上传正确的算法。


后续代码(正确代码)这是查找所有子序列并将它们大写的代码。假设所有字符都是唯一的。如何找到指数并以功能方式实现它?

public static void permuteSubsequence(String a)
{
int n=a.length();
for(int i=0;i<(1<<n);i++)
{
String buff="";
for(int j=0;j<n;j++)
{
if(((1<<j)&i)!=0)
{
buff=buff+new Character(a.charAt(j)).toString().toUpperCase();
}
else
{
buff = buff + a.charAt(j);
}
}
System.out.println(buff);
}
}

从上述案例中提取索引。即,1 的索引和大写。


请求

如何使用Java流将上述代码转换为函数式风格?

我面临的问题是在 map 方法中模拟索引范围。此外,是否有一种方法可以生成字符串的流以将相同的字符串复制到所有元素中,类似于 IntStream.range(a,b)

public static List<String> permuteStreams(String a)
{
int l=(int)(Math.pow(2,a.length())-1)
ArrayList<String> al = new ArrayList<>();
for(int i=0;i<=l;i++)
al.add(a);//Generate a stream and copy back into arraylist maybe if possible?

List<String> sl = al.stream()
.map()//incomplete code
.collect(Collectors.toList());
return sl;
}

最佳答案

不要通过拆分和连接来排列字符串,这是一个非常昂贵的操作,而且完全没有必要。考虑到“大写”和“小写”恰好是两种状态,两种状态项目的排列组合应该敲响警钟,我们正在谈论 binary numbers .计算机中的整数是位的组合,具有两种状态,遍历这些位的所有可能排列就像遍历整数范围一样简单。

0, 1, 2, 3, 4, 5, 6, 7 范围的二进制数表示是 000, 001, 010, 011, 100, 101, 110, 111。现在假设 0 代表“小写”,1 代表三个字符的字符串的“大写”,您就快完成了。

所以剩下的任务就是根据相关位是否设置将String的字符转为大写或小写。有几种方法可以实现这一点。以下代码创建一个最初为小写的字符串作为所有迭代的起点,并将字符切换为大写(如果设置了一位):

public static void permuteSubsequence(String s) {
if(s.isEmpty()) {
System.out.println();
return;
}
String lower = s.toLowerCase(), upper = s.toUpperCase();
if(s.length()!=lower.length() || s.length()!=upper.length())
throw new UnsupportedOperationException("non trivial case mapping");
LongStream.range(0, 1L<<Math.min(lower.length(), 62))
.mapToObj(l -> {
StringBuilder sb=new StringBuilder(lower);
BitSet.valueOf(new long[] { l }).stream()
.forEach(ix -> sb.setCharAt(ix, upper.charAt(ix)));
return sb.toString();
})
.forEach(System.out::println);
}

请注意,此实现仅通过置换较长字符串的前 62 个字符来作弊,因为用于迭代的带符号 long 不允许更多,但置换 62 个字符已经允许 4611686018427387904 组合,所以即使我们假设打印一个变体只需要一纳秒,我们也需要一百多年的时间来打印它们。所以您永远不会注意到作弊行为。

字符串的大写/小写转换不必生成相同长度的字符串。此实现将拒绝具有非平凡大小写映射的字符串,对于这种排列是不可能的。

要改进的一件事是忽略大小写形式不同的字符。这可以通过首先识别可置换字符(它们的位置)并仅置换这些字符来完成:

public static void permuteSubsequence(String s) {
int[] permutable = IntStream.range(0, s.length())
.filter(i->Character.toLowerCase(s.charAt(i))!=Character.toUpperCase(s.charAt(i)))
.toArray();
if(permutable.length == 0) {
System.out.println(s);
return;
}
String lower = s.toLowerCase(), upper = s.toUpperCase();
if(s.length()!=lower.length() || s.length()!=upper.length())
throw new UnsupportedOperationException("non trivial case mapping");
LongStream.range(0, 1L<<Math.min(permutable.length, 62))
.mapToObj(l -> {
StringBuilder sb=new StringBuilder(lower);
BitSet.valueOf(new long[] { l }).stream()
.map(bit -> permutable[bit])
.forEach(ix -> sb.setCharAt(ix, upper.charAt(ix)));
return sb.toString();
})
.forEach(System.out::println);
}

有了这个,permuteSubsequence("Mr.X"); 将打印

mr.x
Mr.x
mR.x
MR.x
mr.X
Mr.X
mR.X
MR.X

关于java - 如何使用流将此程序转换为 Java 8 函数式风格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40621512/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com