Однострочная Java-строковая случайная перестановка - PullRequest
0 голосов
/ 12 июня 2019

Мне нужен хороший однострочный способ генерации случайной перестановки строки Java.

Вот пример, использующий потоки Java 8, нужного мне направления.

В этом примере я использую "abcd" в качестве входных данных примера, который может производить перестановки, такие как dabc, dbac и т. Д.

Я сократил генерацию перестановки строк до трех строк, но у меня есть ощущение, что она может быть короче.

public static void main(String[] args) {

    List<Character> charList = "abcd".chars().mapToObj(i -> (char) i).collect(Collectors.toList());
    Collections.shuffle(charList);
    String string =  charList.stream().map(String::valueOf).collect(Collectors.joining()); 
    System.out.println(string);
}

Был бы признателен любой способ сделать этот код короче / проще.

EDIT:

Хорошо, я придумала, как мне кажется, эффективное однострочное решение, но оно не очень читабельное, поэтому я, вероятно, разбью его на несколько строк.

Я включил это здесь только для справки. Если кто-то может упростить это, это также будет долгожданным ответом.

String str = "ABCDE";        
String str2 = str.chars().mapToObj(e->(char)e).collect(Collectors.toMap(key -> new Random().nextInt(), value -> value)).values().stream().map(String::valueOf).collect(Collectors.joining());
System.out.println(str2);

Ответы [ 5 ]

2 голосов
/ 12 июня 2019

Чтобы добавить еще один подход, используя random и streams:

    String str = "ABCDE";        
    Random rand = new Random();
    String perm= rand.ints( 0, str.length())
                     .distinct()
                     .limit(str.length())
                     .mapToObj(i->String.valueOf(str.charAt(i))).collect(Collectors.joining());
    System.out.println(perm);
2 голосов
/ 12 июня 2019

Я не верю, что ваш потоковый подход может быть значительно упрощен.Но, на мой взгляд, всегда проще написать простые подпрограммы, чем пытаться адаптировать другие методы.Перестановка на месте проста в написании и значительно меньше накладных расходов, чем потоковый подход.После написания я просто убрал их в библиотеку.

  public static String shuffle(String str) {
      char[] result = str.toCharArray();

      int n = result.length;
      while (n > 0) {
         int v = ThreadLocalRandom.current().nextInt(n);
         char temp = result[v];
         result[v] = result[n - 1];
         result[n - 1] = temp;
         n--;
      }
      return new String(result);
   }
1 голос
/ 12 июня 2019

С комментарий :

В идеале мне бы хотелось, чтобы оно было коротким и простым

Использование Apache Commons Lang class ArrayUtils и его shuffle(char[] array) метод.

public static String permute(String s) {
    char[] buf = s.toCharArray();
    ArrayUtils.shuffle(buf);
    return new String(buf);
}

Это просто и очень легко понять.

1 голос
/ 12 июня 2019

Не особо короче, но намерение немного яснее.

Random random = new Random();
String chars = "abcd";
StringBuilder sb = new StringBuilder();

Stream.generate(() -> random.nextInt(chars.length()))
             .distinct()
             .limit(chars.length())
             .map(chars::charAt)
             .forEach(sb::append);

System.out.println(sb.toString());

Имейте в виду, что это не самое эффективное решение, потому что генератор случайных чисел будет генерировать дубликаты, которые будут отбрасываться по разным. Для более крупной строки вы можете вместо этого посмотреть перетасовку списка.

0 голосов
/ 12 июня 2019

То, что вы могли бы сделать здесь, это использовать shuffler внутри коллектора.

Пример коллектора для списка перетасовки можно найти в https://stackoverflow.com/a/36391959/7862302

Так что в вашем случае это может выглядеть так:

String string = "abcd".chars()
                      .mapToObj(i -> (char) i)
                      .collect(toShuffledList())
                      .stream()
                      .map(String::valueOf)
                      .collect(Collectors.joining()); 

Вы могли бы даже ввести коллектор для перетасовки в String:

public static <T> Collector<CharSequence, ?, String> shuffleToString() {
    return Collectors.collectingAndThen(
        Collectors.toCollection(ArrayList::new),
        list -> {
            Collections.shuffle(list);
            return list.stream().collect(Collectors.joining());
        });
}

С этим коллектором это будет выглядеть так:

    String string = "abcd".chars()
                          .mapToObj(i -> (char) i)
                          .map(String::valueOf)
                          .collect(shuffleToString());
    System.out.println(string);
...