如何在不使用 Collections.shuffle(...) 的情况下打乱字符串中的字符?

发布于 2024-09-11 06:16:43 字数 109 浏览 4 评论 0原文

如何打乱字符串中的字符(例如 hello 可以是 ehlol 或 lleoh 或...)。我不想使用 Collections.shuffle(...) 方法,有没有更简单的方法?

How do I shuffle the characters in a string (e.g. hello could be ehlol or lleoh or ...). I don't want to use the Collections.shuffle(...) method, is there anything simpler?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

旧夏天 2024-09-18 06:16:45

我不知道有什么更简单的事情。但是您可以使用 Math.rand() 功能在字符长度范围内生成一个随机数而无需替换,这将为您提供打乱的输出

public class Shuffle {
    public static void main(String[] args) {
        Shuffle s = new Shuffle();
        s.shuffle("hello");

    }
    public void shuffle(String input){
        List<Character> characters = new ArrayList<Character>();
        for(char c:input.toCharArray()){
            characters.add(c);
        }
        StringBuilder output = new StringBuilder(input.length());
        while(characters.size()!=0){
            int randPicker = (int)(Math.random()*characters.size());
            output.append(characters.remove(randPicker));
        }
        System.out.println(output.toString());
    }
}
/*
Sample outputs
hlleo
llheo
leohl
lleho
*/

I dont know anything simpler. But you can use the Math.rand() functionality to generate a random number within the range of the character's length without replace and that would give you a shuffled output

public class Shuffle {
    public static void main(String[] args) {
        Shuffle s = new Shuffle();
        s.shuffle("hello");

    }
    public void shuffle(String input){
        List<Character> characters = new ArrayList<Character>();
        for(char c:input.toCharArray()){
            characters.add(c);
        }
        StringBuilder output = new StringBuilder(input.length());
        while(characters.size()!=0){
            int randPicker = (int)(Math.random()*characters.size());
            output.append(characters.remove(randPicker));
        }
        System.out.println(output.toString());
    }
}
/*
Sample outputs
hlleo
llheo
leohl
lleho
*/
意犹 2024-09-18 06:16:45

性能不是很好,但在我看来相当可读:

public static String shuffleString(String string)
{
  List<String> letters = Arrays.asList(string.split(""));
  Collections.shuffle(letters);
  String shuffled = "";
  for (String letter : letters) {
    shuffled += letter;
  }
  return shuffled;
}

Not great performance, but quite readable in my opinion:

public static String shuffleString(String string)
{
  List<String> letters = Arrays.asList(string.split(""));
  Collections.shuffle(letters);
  String shuffled = "";
  for (String letter : letters) {
    shuffled += letter;
  }
  return shuffled;
}
失退 2024-09-18 06:16:45

这个怎么样:

public static String shuffle(String text) {
    char[] characters = text.toCharArray();
    for (int i = 0; i < characters.length; i++) {
        int randomIndex = (int)(Math.random() * characters.length);
        char temp = characters[i];
        characters[i] = characters[randomIndex];
        characters[randomIndex] = temp;
    }
    return new String(characters);
}

How about this:

public static String shuffle(String text) {
    char[] characters = text.toCharArray();
    for (int i = 0; i < characters.length; i++) {
        int randomIndex = (int)(Math.random() * characters.length);
        char temp = characters[i];
        characters[i] = characters[randomIndex];
        characters[randomIndex] = temp;
    }
    return new String(characters);
}
我早已燃尽 2024-09-18 06:16:45

多么烦人的问题啊。我最终得到了这个:

import java.util.Collections;
import com.google.common.primitives.Chars;
import org.apache.commons.lang3.StringUtils;

String shuffle(String s) {
    List<Character> chars = Chars.asList(s.toCharArray());
    Collections.shuffle(chars);
    return StringUtils.join(chars.stream().toArray());
}

是的,两个库:)

What an annoying problem. I finally ended up with this:

import java.util.Collections;
import com.google.common.primitives.Chars;
import org.apache.commons.lang3.StringUtils;

String shuffle(String s) {
    List<Character> chars = Chars.asList(s.toCharArray());
    Collections.shuffle(chars);
    return StringUtils.join(chars.stream().toArray());
}

Yes, two libraries :)

流云如水 2024-09-18 06:16:45

例如:

static String shuffle(String text){
    if (text.length()<=1)
        return text;

    int split=text.length()/2;

    String temp1=shuffle(text.substring(0,split));
    String temp2=shuffle(text.substring(split));

    if (Math.random() > 0.5) 
        return temp1 + temp2;
    else 
        return temp2 + temp1;
}    

E.g.:

static String shuffle(String text){
    if (text.length()<=1)
        return text;

    int split=text.length()/2;

    String temp1=shuffle(text.substring(0,split));
    String temp2=shuffle(text.substring(split));

    if (Math.random() > 0.5) 
        return temp1 + temp2;
    else 
        return temp2 + temp1;
}    
↘紸啶 2024-09-18 06:16:45
class ShuffleString
{

    public static String shuffle(String s)
    {

        String shuffledString = ""; 

        while (s.length() != 0)
        {
            int index = (int) Math.floor(Math.random() * s.length());
            char c = s.charAt(index);
            s = s.substring(0,index)+s.substring(index+1);
            shuffledString += c;
        }

        return shuffledString;

    }

}


public class foo{
    static public void main(String[] args)
    {

        String test = "hallo";
        test = ShuffleString.shuffle(test);
        System.out.println(test);
    }
}

输出:
阿赫洛尔

class ShuffleString
{

    public static String shuffle(String s)
    {

        String shuffledString = ""; 

        while (s.length() != 0)
        {
            int index = (int) Math.floor(Math.random() * s.length());
            char c = s.charAt(index);
            s = s.substring(0,index)+s.substring(index+1);
            shuffledString += c;
        }

        return shuffledString;

    }

}


public class foo{
    static public void main(String[] args)
    {

        String test = "hallo";
        test = ShuffleString.shuffle(test);
        System.out.println(test);
    }
}

Output:
ahlol

触ぅ动初心 2024-09-18 06:16:45

下面的代码既不需要递归,也不需要转换为集合。

public static String shuffle(String string) {
    StringBuilder sb = new StringBuilder(string.length());
    double rnd;
    for (char c: string.toCharArray()) {
        rnd = Math.random();
        if (rnd < 0.34)
            sb.append(c);
        else if (rnd < 0.67)
            sb.insert(sb.length() / 2, c);
        else
            sb.insert(0, c);
    }       
    return sb.toString();
}

Here's code that requires neither recursion, nor converting to a Collection.

public static String shuffle(String string) {
    StringBuilder sb = new StringBuilder(string.length());
    double rnd;
    for (char c: string.toCharArray()) {
        rnd = Math.random();
        if (rnd < 0.34)
            sb.append(c);
        else if (rnd < 0.67)
            sb.insert(sb.length() / 2, c);
        else
            sb.insert(0, c);
    }       
    return sb.toString();
}
预谋 2024-09-18 06:16:45

不知道为什么你不想使用随机播放,除非是为了学校。 ;)

如果您关心性能,您绝对不能使用任何用“+”连接字符串的解决方案。

这是我能想到的最紧凑的解决方案:

public static String shuffle(String string) {
    if (StringUtils.isBlank(string) {
        return string;
    }

    final List<Character> randomChars = new ArrayList<>();
    CollectionUtils.addAll(randomChars, ArrayUtils.toObject(string.toCharArray()));
    Collections.shuffle(randomChars);
    return StringUtils.join(randomChars, "");
}

Not sure why you wouldn't want to use shuffle, unless it's for school. ;)

And if you're concerned with performance, you definitely can't use any solution that concatenates strings with "+".

Here's the most compact solution I could come up with:

public static String shuffle(String string) {
    if (StringUtils.isBlank(string) {
        return string;
    }

    final List<Character> randomChars = new ArrayList<>();
    CollectionUtils.addAll(randomChars, ArrayUtils.toObject(string.toCharArray()));
    Collections.shuffle(randomChars);
    return StringUtils.join(randomChars, "");
}
荭秂 2024-09-18 06:16:45

没有外部库,对于那些不介意使用 Collections.shuffle() 的人:

static String shuffle(String string){

    List<Character> list = string.chars().mapToObj(c -> new Character((char) c))
                                         .collect(Collectors.toList());
    Collections.shuffle(list);
    StringBuilder sb = new StringBuilder();
    list.forEach(c -> sb.append(c));

    return sb.toString();
}

Without external libraries, for those who do not mind using Collections.shuffle():

static String shuffle(String string){

    List<Character> list = string.chars().mapToObj(c -> new Character((char) c))
                                         .collect(Collectors.toList());
    Collections.shuffle(list);
    StringBuilder sb = new StringBuilder();
    list.forEach(c -> sb.append(c));

    return sb.toString();
}
眸中客 2024-09-18 06:16:45

在 Kotlin 中,您可以执行以下操作。

val helloCharArray = "hello".toCharArray()
helloCharArray.shuffle()
val shuffledHello = helloCharArray.concatToString()

In Kotlin, you can do the following.

val helloCharArray = "hello".toCharArray()
helloCharArray.shuffle()
val shuffledHello = helloCharArray.concatToString()
晨曦÷微暖 2024-09-18 06:16:45

您可以迭代所有字符,将每个字符与下一个字符进行比较。那么如果 Math.rand() > 0.5 将此字符与下一个字符交换,否则移至下一个字符。

You could iterate over all the characters, comparing each one with the next. Then if Math.rand() > 0.5 swap this character with the next, otherwise move on to the next character.

不忘初心 2024-09-18 06:16:45
        String shuffled;
        do {
            shuffled = Stream.of(text.split("")).sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(3) - 1).collect(Collectors.joining());
        }while(shuffled.equals(text));
        String shuffled;
        do {
            shuffled = Stream.of(text.split("")).sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(3) - 1).collect(Collectors.joining());
        }while(shuffled.equals(text));
柠檬 2024-09-18 06:16:45

如果仍想恢复原来的 String稍后,尝试这样的事情:

public static class ShuffledString
{
    private List<Integer> indices;
    private String string;

    public ShuffledString(List<Integer> indices, String string)
    {
        this.indices = indices;
        this.string = string;
    }

    public List<Integer> getIndices()
    {
        return indices;
    }

    public String getRegularString()
    {
        StringBuilder stringBuilder = new StringBuilder();

        for (int stringIndex = 0; stringIndex < indices.size(); stringIndex++)
        {
            int characterIndex = indices.indexOf(stringIndex);
            stringBuilder.append(string.charAt(characterIndex));
        }

        return stringBuilder.toString();
    }
}

public static ShuffledString shuffle(String input)
{
    List<Integer> indices = new ArrayList<>();

    StringBuilder output = new StringBuilder(input.length());
    while (indices.size() < input.length())
    {
        int randomIndex;

        while (indices.contains(randomIndex = (int) (Math.random() * input.length())))
        {

        }

        indices.add(randomIndex);
        output.append(input.charAt(randomIndex));
    }

    return new ShuffledString(indices, output.toString());
}

If you still want to restore the original String later on, try something like this:

public static class ShuffledString
{
    private List<Integer> indices;
    private String string;

    public ShuffledString(List<Integer> indices, String string)
    {
        this.indices = indices;
        this.string = string;
    }

    public List<Integer> getIndices()
    {
        return indices;
    }

    public String getRegularString()
    {
        StringBuilder stringBuilder = new StringBuilder();

        for (int stringIndex = 0; stringIndex < indices.size(); stringIndex++)
        {
            int characterIndex = indices.indexOf(stringIndex);
            stringBuilder.append(string.charAt(characterIndex));
        }

        return stringBuilder.toString();
    }
}

public static ShuffledString shuffle(String input)
{
    List<Integer> indices = new ArrayList<>();

    StringBuilder output = new StringBuilder(input.length());
    while (indices.size() < input.length())
    {
        int randomIndex;

        while (indices.contains(randomIndex = (int) (Math.random() * input.length())))
        {

        }

        indices.add(randomIndex);
        output.append(input.charAt(randomIndex));
    }

    return new ShuffledString(indices, output.toString());
}
濫情▎り 2024-09-18 06:16:45

在 Java 8+ 中,可以使用 Collectors.shuffle(...) 在三行中完成此操作,如下所示:

  1. 将字符串转换为字符列表
  2. 随机排列列表
  3. 将随机排列的字符列表转换回a String

代码:

public static String shuffle(final String str) {
    List<Character> chars = str.chars().mapToObj(e->(char)e).collect(Collectors.toList());
    Collections.shuffle(chars);
    return chars.stream().map(e->e.toString()).collect(Collectors.joining());
}

演示:

Rextester 演示

In Java 8+ this can be done using Collectors.shuffle(...) in three lines as follows:

  1. Convert the String into a List of Characters
  2. Shuffle the list
  3. Convert the shuffled List of Characters back into a String

Code:

public static String shuffle(final String str) {
    List<Character> chars = str.chars().mapToObj(e->(char)e).collect(Collectors.toList());
    Collections.shuffle(chars);
    return chars.stream().map(e->e.toString()).collect(Collectors.joining());
}

Demo:

Rextester demo

带刺的爱情 2024-09-18 06:16:45

使用 commons-lang3

import org.apache.commons.lang3.ArrayUtils;

String shuffle(String text) {
    char[] chars = text.toCharArray();
    ArrayUtils.shuffle(chars);
    return String.valueOf(chars);
}

Using commons-lang3:

import org.apache.commons.lang3.ArrayUtils;

String shuffle(String text) {
    char[] chars = text.toCharArray();
    ArrayUtils.shuffle(chars);
    return String.valueOf(chars);
}
物价感观 2024-09-18 06:16:45

使用 Stream API 的另一种简短实现:

 String shuffle(String str) {       
    return new Random().ints(0, str.length()).distinct().limit(str.length()) // shuffle indexes
            .mapToObj(i->""+str.charAt(i)).collect(Collectors.joining());    // collect letters
 }

One more short implementation using Stream API:

 String shuffle(String str) {       
    return new Random().ints(0, str.length()).distinct().limit(str.length()) // shuffle indexes
            .mapToObj(i->""+str.charAt(i)).collect(Collectors.joining());    // collect letters
 }
阳光下慵懒的猫 2024-09-18 06:16:45

某些String可能包含由多个字符组成的符号。

为了解决这个问题,您可以将 String 转换为代码点,对数组进行打乱,然后将它们转换回 String

public static String shuffle(String toShuffle){
    int[] codePoints = toShuffle.codePoints().toArray();
    shuffle(codePoints);
    return new String(codePoints, 0, codePoints.length);
}

可以像 this 或使用任何其他方法来完成数组的洗牌:

//code from https://stackoverflow.com/a/1520212/10871900
private static void shuffle(int[] ar)
  {
    // If running on Java 6 or older, use `new Random()` on RHS here
    Random rnd = ThreadLocalRandom.current();
    for (int i = ar.length - 1; i > 0; i--)
    {
      int index = rnd.nextInt(i + 1);
      // Simple swap
      int a = ar[index];
      ar[index] = ar[i];
      ar[i] = a;
    }
  }

作为性能较差的替代方案,您可以使用包装对象并随机播放流:

public static String shuffle(String toShuffle){
    int[] codePoints = toShuffle
        .codePoints()
        .boxed()
        .sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(-1, 2) //https://stackoverflow.com/a/55352119/10871900 
        .mapToInt(i->i)
        .toArray();
    return new String(codePoints, 0, codePoints.length);
}

Some Strings may contain symbols consisting of multiple characters.

In order to get around this, you can convert the String to code points, shuffle the array and convert them back to a String.

public static String shuffle(String toShuffle){
    int[] codePoints = toShuffle.codePoints().toArray();
    shuffle(codePoints);
    return new String(codePoints, 0, codePoints.length);
}

Shuffling the array could be done like this or using any other method:

//code from https://stackoverflow.com/a/1520212/10871900
private static void shuffle(int[] ar)
  {
    // If running on Java 6 or older, use `new Random()` on RHS here
    Random rnd = ThreadLocalRandom.current();
    for (int i = ar.length - 1; i > 0; i--)
    {
      int index = rnd.nextInt(i + 1);
      // Simple swap
      int a = ar[index];
      ar[index] = ar[i];
      ar[i] = a;
    }
  }

As a less-performant alternative, you could use wrapper objects and shuffle the stream:

public static String shuffle(String toShuffle){
    int[] codePoints = toShuffle
        .codePoints()
        .boxed()
        .sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(-1, 2) //https://stackoverflow.com/a/55352119/10871900 
        .mapToInt(i->i)
        .toArray();
    return new String(codePoints, 0, codePoints.length);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文