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

如何从{a1 | a2 | a3}格式的字符串中获得N个随机字符串?

  •  3
  • Pentium10  · 技术社区  · 14 年前

    string s1="planets {Sun|Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune}{?|!|.}"
    string s2="some text {morning,night,evening} some text{?|!|.}"
    

    我如何从集合中随机选择N,然后用逗号连接它们。集合在{}之间定义,选项用| pipe分隔 维持秩序。字符串可以有多个集合{}。

    string output1="planets Sun, Venus.";
    string output2="planets Neptune!";
    string output3="planets Earth, Saturn, Uranus, Neptune.";
    string output4="planets Uranus, Saturn.";// bad example, order is not correct
    string output5="some text morning!";
    

    5 回复  |  直到 12 年前
        1
  •  3
  •   Marcelo Cantos    14 年前

    将行星排列成一个阵列,移除随机元素直到你有足够的空间。从算法上讲,有更可爱的解决方案,但对于处理的数据量来说,这既快速又简单。

        2
  •  0
  •   Itay Karo    14 年前

    我不确定java的语法,但应该是这样的。

    string[] split = s.split("|");
    Random r = new Random();
    int first = r.nextInt(split.length);
    string planets = "planets " + split[first++];
    for (; first < split.length; first++)
    {
        if (r.nextInt(2) == 1)
             planets += " " + split[first];
    }
    
        3
  •  0
  •   tucuxi    14 年前

    这是另一个选择。这个只能从中选择一个元素 {|||} 设置,并在中的1到N个元素之间进行选择 {,,,}

    public static String generateVariant(String s) {
        Pattern p = Pattern.compile("[{]([^}]+)[}]");
        Matcher m = p.matcher(s);
        StringBuilder output = new StringBuilder();
    
        int offset = 0;
        while (m.find()) {
            output.append(s.substring(offset, m.start()));
            String[] choices = m.group(1).split("[|,]");
    
            // if '|' used as separator, only echo 1 random choice
            int n = m.group(1).contains("|") ? 1
                    : (int) (Math.random() * (choices.length - 1)) + 1;
    
            // permutation with n random elements
            int[] permutation = new int[choices.length];
            for (int i = 0; i < choices.length; i++) {
                permutation[i] = i;
            }
            for (int i=0; i<n; i++) {
                int r = (int)(Math.random() * (choices.length - i)) + i;
                int aux = permutation[r];
                permutation[r] = permutation[i];
                permutation[i] = aux;
            }
    
            // sort and echo first n
            Arrays.sort(permutation, 0, n);
            for (int i=0; i<n; i++) {
                output.append((i == 0 ? "" : ", ") + choices[permutation[i]]);
            }
            offset = m.end();
        }
        output.append(s.substring(offset, s.length()));
        return output.toString();
    }
    
    public static void main(String[] args) {
        String s1 = "planets {Sun,Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune}{?|!|.}";
        for (int i = 0; i < 10; i++) {
            System.err.println(generateVariant(s1));
        }
    }
    

    {|||} 套。下面是一个简短的版本,其中选择数的分布不再是统一的(灵感来自丹尼尔·特雷宾的答案):

    public static String generateVariant(String s) {
        Pattern p = Pattern.compile("[{]([^}]+)[}]");
        Matcher m = p.matcher(s);
        StringBuilder output = new StringBuilder();
        Random r = new Random();
    
        int offset = 0;
        while (m.find()) {
            output.append(s.substring(offset, m.start()));
            String[] choices = m.group(1).split("[|,]");
            // if '|' used as separator, only echo 1 random choice
            if (m.group(1).contains("|")) {
                output.append(choices[r.nextInt(choices.length)]);
            } else {
                boolean first = true;
                for (int i=0; i<choices.length; i++) {
                    if (r.nextBoolean()) {
                        output.append((first ? "" : ", ") + choices[i]);
                        first = false;
                    }
                }                
            }
            offset = m.end();
        }
        output.append(s.substring(offset, s.length()));
        return output.toString();
    }
    
        4
  •  0
  •   Daniel Trebbien    14 年前

    我测试了这个Java程序,它可以工作:

    import java.util.Random;
    
    /** @author Daniel Trebbien */
    // License: Public Domain
    public class SO2965185 {
        public static String randomFormat(final String templ) {
            int i = templ.indexOf('{');
            if (i < 0) {
                return templ;
            }
            else {
                Random r = new Random();
    
                int prevI = 0;
                StringBuilder sb = new StringBuilder();
                do {
                    sb.append(templ, prevI, i);
                    int j = templ.indexOf('}', i + 1);
                    if (j < 0)
                        throw new java.util.MissingFormatArgumentException(templ.substring(i));
                    int pipeCount = 0;
                    for (int k = templ.indexOf('|', i + 1); i < k && k < j; k = templ.indexOf('|', k + 1))
                        ++pipeCount;
                    if (pipeCount == 0) {
                        sb.append(templ, i + 1, j);
                    }
                    else {
                        String m0Selection;
                        final int m0 = r.nextInt(pipeCount + 1); // must pick one from each set
                        if (m0 >= pipeCount) {
                            m0Selection = templ.substring(templ.lastIndexOf('|', j - 1) + 1, j);
                        }
                        else {
                            int k = i + 1;
                            int m = m0;
                            for(; m > 0; --m)
                                k = templ.indexOf('|', k) + 1;
                            m0Selection = templ.substring(k, templ.indexOf('|', k + 1));
                        }
    
                        int selectionCount = 0;
                        for (int n = 0; n <= pipeCount; ++n) {
                            if (n == m0) {
                                if (selectionCount != 0)
                                    sb.append(", ");
                                sb.append(m0Selection);
                                ++selectionCount;
                            }
                            else if (r.nextBoolean()) {
                                int m = n;
                                if (selectionCount != 0)
                                    sb.append(", ");
                                if (m >= pipeCount) {
                                    sb.append(templ, templ.lastIndexOf('|', j - 1) + 1, j);
                                }
                                else {
                                    int k = i + 1;
                                    for(; m > 0; --m)
                                        k = templ.indexOf('|', k) + 1;
                                    sb.append(templ, k, templ.indexOf('|', k + 1));
                                }
                                ++selectionCount;
                            }
                        }
                    }
                    prevI = j + 1;
                    i = templ.indexOf('{', j + 1);
                } while(i >= 0);
                return sb.toString();
            }
        }
    
        public static void main(String[] args) {
            System.out.println(randomFormat("test"));
            System.out.println(randomFormat("{oneOption}"));
            System.out.println(randomFormat("{first|second}"));
            String s1 = "planets {Sun|Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune}{?|!|.}";
            System.out.println(randomFormat(s1));
            //System.out.println(randomFormat("jjj{test"));
        }
    }
    

    test
    oneOption
    first, second
    planets Sun, Mercury, Jupiter, Neptune?, !, .
    

    test
    oneOption
    second
    planets Sun, Jupiter, Saturn!, .
    

    test
    oneOption
    first
    planets Venus, Earth, Jupiter, Saturn, Uranus, Neptune.
    

    代码从每个集合中选择至少有一个条目的条目的随机组合。所以,对于一套 N 条目,共有2个 N M 随机组合中的条目:

    P(正是 M 生成的组合中的条目)=( 选择 M N

    例子: N = 9 ( "{Sun|Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune}" ).

    P(生成的组合中正好有2个条目)= 0.0704

        5
  •  0
  •   dev13    12 年前

    对于行星,只要写一个循环

    result = empty list
    For p in planets
      throw a dice
      If (dice > 3) // 50% probability, adjust as required
        append p to result
    If result is empty, start over // do this if you don't want result to be empty