我有一些内容未知的随机字符串,众所周知,内容是字母数字,小写。
我正在寻找一种简单的方法来大写该字符串中随机数字的字符。随机性越高越好。
我可以想到几种方法来做到这一点,但它们似乎都不是最优的。
好的第一个解决方案:
public String randomizeCase(String myString){
Random rand = new Random();
StringBuilder build = new StringBuilder();
for(char c: myString.toCharArray()){
String s = new String(c);
if(Character.isLetter(c) && rand.nextBoolean()){
s = s.toUpperCase();
}
build.append(s);
}
return build.toString();
}
我不喜欢这个解决方案,因为:
答案 0 :(得分:5)
解决方案取决于您选择的概率模型。例如,如果你决定binomial distribution,那么你可以遍历字符,并以固定的概率p将每个字符串切换为大写。预期的大写字母数将是p * str.length():
public static String randomUpper(String str, double p) {
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isLetter(c) && Math.random() < p)
c = Character.toUpperCase(c);
sb.append(c);
}
return sb.toString();
}
另一方面,如果您想确定给定字符串的超精确字母的确切数量,则问题变为random sample problem(即选择M个位置以切换字符串中的N个位置)。这可能比第一种方法快得多,当M远小于N时(尽管使用Java的不可变字符串,差异变得很小,因为你必须复制整个字符串)。
- 编辑 -
现在您已阐明要求,请考虑以下事项:
public static String randomUpper2(String str, double p) {
int letters = 0;
for (int i = 0; i < str.length(); i++) {
if (Character.isLetter(str.charAt(i)))
letters++;
}
int toChoose = (int) (p * letters);
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isLetter(c)) {
if (Math.random() < (toChoose/(double)letters)) {
c = Character.toUpperCase(c);
toChoose--;
}
letters--;
}
sb.append(c);
}
return sb.toString();
}
此代码根据需要“动态”执行随机样本,仅考虑alpha字符。使用p = 0.5来切换正好一半的字母。
答案 1 :(得分:3)
以下是随机样本问题的代码段(感谢Eyal为其命名)。不确定这是否是您正在寻找的。 p>
请注意,如果字符串中没有足够的小写字母,则此解决方案将遇到infinete循环。所以你也需要解决这个问题,但我想这是一个起点。 ; - )
String myString = "9aie3ra3nr23rr5r21t";
System.out.println(upperCaseRandom(myString, 10));
public static String upperCaseRandom(String input, int n) {
StringBuilder output = new StringBuilder(input);
Random r = new Random();
for (int i = 0; i < n; i++) {
// Pick a place
int position = r.nextInt(input.length());
// Check if lowercase alpha
if (Character.isLowerCase(output.charAt(position))) {
output.setCharAt(position, Character.toUpperCase(output.charAt(position)));
} else {
i--;
}
}
return output.toString();
}
修改强> 这是一个改进版本。它确实将n个小写字母更改为大写字母(如果有足够的话,则会更改所有字母)。程序不会遇到无限循环,但仍然运行时间是一个问题。
public static String upperCaseRandom(String input, int n) {
final int length = input.length();
final StringBuilder output = new StringBuilder(input);
final boolean[] alreadyChecked = new boolean[length];
final Random r = new Random();
for (int i = 0, checks = 0; i < n && checks < length; i++) {
// Pick a place
int position = r.nextInt(length);
// Check if lowercase alpha
if (!alreadyChecked[position]) {
if (Character.isLowerCase(output.charAt(position))) {
output.setCharAt(position, Character.toUpperCase(output.charAt(position)));
} else {
i--;
}
checks++;
alreadyChecked[position] = true;
} else {
i--;
}
}
return output.toString();
}
答案 2 :(得分:0)
我试过
String lowerCasedRandomString = "4210281f-76ac-96b5-ed54-5458abf788d0";
String upperCasedRandomString = "4210281F-76AC-96B5-ED54-5458ABF788D0";
System.out.println(lowerCasedRandomString.toUpperCase());
System.out.println(upperCasedRandomString.toLowerCase());
我得到了输出
4210281F-76AC-96B5-ED54-5458ABF788D0
4210281f-76ac-96b5-ed54-5458abf788d0