代码之家  ›  专栏  ›  技术社区  ›  mkoryak

随机字母数字字符串中的随机大写字符数

  •  1
  • mkoryak  · 技术社区  · 15 年前

    我有一些未知内容的随机字符串,已知的是内容是字母数字和小写。

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

    我可以想出一些方法来做到这一点,但它们似乎都不是很理想。

    第一种解决方案:

    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();
    }
    

    • 每个字符大写的50%概率并不等于50%字符大写的50%
    • 字符到字符串的转换很难看
    3 回复  |  直到 15 年前
        1
  •  3
  •   Nils Schmidt    15 年前

    下面是 随机抽样问题

    请注意,如果字符串中没有足够的小写字母,此解决方案将运行到中网循环中。所以你也需要解决这个问题,但我想这是一个起点

    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
  •  6
  •   Eyal Schneider    15 年前

    解决方案取决于您选择的概率模型。例如,如果你决定 binomial distribution

    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 (即,从字符串中的N个位置中选择M个位置进行切换)。这可能比第一种方法快得多,当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来精确切换一半的字母。

        3
  •  0
  •   Er Kaushik Chakraborty    10 年前

    我试过了

          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