来自随机字母数字字符串的大写随机字符数

mko*_*yak 1 java string random

我有一些内容未知的随机字符串,众所周知的是内容是字母数字和小写.

我正在寻找一种简单的方法来大写该字符串中随机数字的字符.随机性越高越好.

我可以想到几种方法来做到这一点,但它们似乎都不是最优的.

好的第一个解决方案:

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();
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个解决方案,因为:

  • 每个字符大写的几率为50%,不等于50%的字符大写的几率为50%
  • 有可能没有任何东西得到满足
  • char到字符串转换很难看

Eya*_*der 5

解决方案取决于您选择的概率模型.例如,如果你决定二项分布,那么你可以遍历字符,并以固定的概率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();
}
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您想要确定给定字符串的超精确字母的确切数量,则问题变成随机样本问题(即选择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();
}
Run Code Online (Sandbox Code Playgroud)

此代码根据需要"动态"执行随机样本,仅考虑alpha字符.使用p = 0.5来切换正好一半的字母.