Willekeurige shuffelen van een array

Ik moet willekeurig de volgende array schudden:

int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};

Is er een functie om dat te doen?


Antwoord 1, Autoriteit 100%

Gebruik van collecties om een ​​reeks primitieve typen te schudden is een beetje een overkill …

Het is eenvoudig genoeg om de functie zelf te implementeren, met behulp van bijvoorbeeld de fisher-yates shuffle :

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
class Test
{
  public static void main(String args[])
  {
    int[] solutionArray = { 1, 2, 3, 4, 5, 6, 16, 15, 14, 13, 12, 11 };
    shuffleArray(solutionArray);
    for (int i = 0; i < solutionArray.length; i++)
    {
      System.out.print(solutionArray[i] + " ");
    }
    System.out.println();
  }
  // Implementing Fisher–Yates shuffle
  static void shuffleArray(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;
    }
  }
}

Antwoord 2, Autoriteit 62%

Hier is een eenvoudige manier met behulp van een ArrayList:

List<Integer> solution = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
    solution.add(i);
}
Collections.shuffle(solution);

Antwoord 3, Autoriteit 37%

Hier is een werkende en efficiënte Fisher-Yates shuffle array-functie:

private static void shuffleArray(int[] array)
{
    int index;
    Random random = new Random();
    for (int i = array.length - 1; i > 0; i--)
    {
        index = random.nextInt(i + 1);
        if (index != i)
        {
            array[index] ^= array[i];
            array[i] ^= array[index];
            array[index] ^= array[i];
        }
    }
}

of

private static void shuffleArray(int[] array)
{
    int index, temp;
    Random random = new Random();
    for (int i = array.length - 1; i > 0; i--)
    {
        index = random.nextInt(i + 1);
        temp = array[index];
        array[index] = array[i];
        array[i] = temp;
    }
}

Antwoord 4, autoriteit 9%

Collecties klasse heeft een efficiënte methode om te shuffelen, die kan worden gekopieerd, om er niet afhankelijk van te zijn:

/**
 * Usage:
 *    int[] array = {1, 2, 3};
 *    Util.shuffle(array);
 */
public class Util {
    private static Random random;
    /**
     * Code from method java.util.Collections.shuffle();
     */
    public static void shuffle(int[] array) {
        if (random == null) random = new Random();
        int count = array.length;
        for (int i = count; i > 1; i--) {
            swap(array, i - 1, random.nextInt(i));
        }
    }
    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

Antwoord 5, autoriteit 5%

Bekijk de Collectionsklasse, in het bijzonder shuffle(...).


Antwoord 6, autoriteit 4%

Hier is een complete oplossing met behulp van de Collections.shuffle-aanpak:

public static void shuffleArray(int[] array) {
  List<Integer> list = new ArrayList<>();
  for (int i : array) {
    list.add(i);
  }
  Collections.shuffle(list);
  for (int i = 0; i < list.size(); i++) {
    array[i] = list.get(i);
  }    
}

Merk op dat het lijdt onder het onvermogen van Java om soepel te vertalen tussen int[]en Integer[](en dus int[]en List<Integer>).


Antwoord 7, autoriteit 4%

Je hebt hier een aantal opties. Een lijst is een beetje anders dan een array als het gaat om shuffelen.

Zoals je hieronder kunt zien, is een array sneller dan een lijst, en een primitieve array is sneller dan een objectarray.

Voorbeeldduur

List<Integer> Shuffle: 43133ns
    Integer[] Shuffle: 31884ns
        int[] Shuffle: 25377ns

Hieronder staan drie verschillende implementaties van een shuffle. U dient Collections.shuffle alleen te gebruiken als u te maken heeft met een verzameling. Het is niet nodig om uw array in een verzameling te wikkelen om deze te sorteren. De onderstaande methoden zijn heel eenvoudig te implementeren.

ShuffleUtil-klasse

import java.lang.reflect.Array;
import java.util.*;
public class ShuffleUtil<T> {
    private static final int[] EMPTY_INT_ARRAY = new int[0];
    private static final int SHUFFLE_THRESHOLD = 5;
    private static Random rand;

Hoofdmethode

   public static void main(String[] args) {
        List<Integer> list = null;
        Integer[] arr = null;
        int[] iarr = null;
        long start = 0;
        int cycles = 1000;
        int n = 1000;
        // Shuffle List<Integer>
        start = System.nanoTime();
        list = range(n);
        for (int i = 0; i < cycles; i++) {
            ShuffleUtil.shuffle(list);
        }
        System.out.printf("%22s: %dns%n", "List<Integer> Shuffle", (System.nanoTime() - start) / cycles);
        // Shuffle Integer[]
        start = System.nanoTime();
        arr = toArray(list);
        for (int i = 0; i < cycles; i++) {
            ShuffleUtil.shuffle(arr);
        }
        System.out.printf("%22s: %dns%n", "Integer[] Shuffle", (System.nanoTime() - start) / cycles);
        // Shuffle int[]
        start = System.nanoTime();
        iarr = toPrimitive(arr);
        for (int i = 0; i < cycles; i++) {
            ShuffleUtil.shuffle(iarr);
        }
        System.out.printf("%22s: %dns%n", "int[] Shuffle", (System.nanoTime() - start) / cycles);
    }

Een generieke lijst shuffelen

   // ================================================================
    // Shuffle List<T> (java.lang.Collections)
    // ================================================================
    @SuppressWarnings("unchecked")
    public static <T> void shuffle(List<T> list) {
        if (rand == null) {
            rand = new Random();
        }
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i = size; i > 1; i--) {
                swap(list, i - 1, rand.nextInt(i));
            }
        } else {
            Object arr[] = list.toArray();
            for (int i = size; i > 1; i--) {
                swap(arr, i - 1, rand.nextInt(i));
            }
            ListIterator<T> it = list.listIterator();
            int i = 0;
            while (it.hasNext()) {
                it.next();
                it.set((T) arr[i++]);
            }
        }
    }
    public static <T> void swap(List<T> list, int i, int j) {
        final List<T> l = list;
        l.set(i, l.set(j, l.get(i)));
    }
    public static <T> List<T> shuffled(List<T> list) {
        List<T> copy = copyList(list);
        shuffle(copy);
        return copy;
    }

een generieke array schuifelen

   // ================================================================
    // Shuffle T[]
    // ================================================================
    public static <T> void shuffle(T[] arr) {
        if (rand == null) {
            rand = new Random();
        }
        for (int i = arr.length - 1; i > 0; i--) {
            swap(arr, i, rand.nextInt(i + 1));
        }
    }
    public static <T> void swap(T[] arr, int i, int j) {
        T tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    public static <T> T[] shuffled(T[] arr) {
        T[] copy = Arrays.copyOf(arr, arr.length);
        shuffle(copy);
        return copy;
    }

Een primitieve array schuifelen

   // ================================================================
    // Shuffle int[]
    // ================================================================
    public static <T> void shuffle(int[] arr) {
        if (rand == null) {
            rand = new Random();
        }
        for (int i = arr.length - 1; i > 0; i--) {
            swap(arr, i, rand.nextInt(i + 1));
        }
    }
    public static <T> void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    public static int[] shuffled(int[] arr) {
        int[] copy = Arrays.copyOf(arr, arr.length);
        shuffle(copy);
        return copy;
    }

Hulpprogramma’s

Eenvoudige hulpprogramma-methoden om arrays naar lijsten te kopiëren en om te zetten en vice versa.

   // ================================================================
    // Utility methods
    // ================================================================
    protected static <T> List<T> copyList(List<T> list) {
        List<T> copy = new ArrayList<T>(list.size());
        for (T item : list) {
            copy.add(item);
        }
        return copy;
    }
    protected static int[] toPrimitive(Integer[] array) {
        if (array == null) {
            return null;
        } else if (array.length == 0) {
            return EMPTY_INT_ARRAY;
        }
        final int[] result = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            result[i] = array[i].intValue();
        }
        return result;
    }
    protected static Integer[] toArray(List<Integer> list) {
        return toArray(list, Integer.class);
    }
    protected static <T> T[] toArray(List<T> list, Class<T> clazz) {
        @SuppressWarnings("unchecked")
        final T[] arr = list.toArray((T[]) Array.newInstance(clazz, list.size()));
        return arr;
    }

Bereikklasse

Genereert een reeks waarden, vergelijkbaar met de functie rangevan Python.

   // ================================================================
    // Range class for generating a range of values.
    // ================================================================
    protected static List<Integer> range(int n) {
        return toList(new Range(n), new ArrayList<Integer>());
    }
    protected static <T> List<T> toList(Iterable<T> iterable) {
        return toList(iterable, new ArrayList<T>());
    }
    protected static <T> List<T> toList(Iterable<T> iterable, List<T> destination) {
        addAll(destination, iterable.iterator());
        return destination;
    }
    protected static <T> void addAll(Collection<T> collection, Iterator<T> iterator) {
        while (iterator.hasNext()) {
            collection.add(iterator.next());
        }
    }
    private static class Range implements Iterable<Integer> {
        private int start;
        private int stop;
        private int step;
        private Range(int n) {
            this(0, n, 1);
        }
        private Range(int start, int stop) {
            this(start, stop, 1);
        }
        private Range(int start, int stop, int step) {
            this.start = start;
            this.stop = stop;
            this.step = step;
        }
        @Override
        public Iterator<Integer> iterator() {
            final int min = start;
            final int max = stop / step;
            return new Iterator<Integer>() {
                private int current = min;
                @Override
                public boolean hasNext() {
                    return current < max;
                }
                @Override
                public Integer next() {
                    if (hasNext()) {
                        return current++ * step;
                    } else {
                        throw new NoSuchElementException("Range reached the end");
                    }
                }
                @Override
                public void remove() {
                    throw new UnsupportedOperationException("Can't remove values from a Range");
                }
            };
        }
    }
}

Antwoord 8, autoriteit 3%

Het gebruik van ArrayList<Integer>kan u helpen het probleem van shuffelen op te lossen zonder veel logica toe te passen en minder tijd te verbruiken. Dit is wat ik voorstel:

ArrayList<Integer> x = new ArrayList<Integer>();
for(int i=1; i<=add.length(); i++)
{
    x.add(i);
}
Collections.shuffle(x);

Antwoord 9, autoriteit 3%

De volgende code zorgt voor een willekeurige volgorde op de array.

// Shuffle the elements in the array
Collections.shuffle(Arrays.asList(array));

van: http://www.programcreek.com/2012/02/java-method-to-shuffle-an-int-array-with-random-order/


Antwoord 10, autoriteit 2%

U kunt Java 8 nu gebruiken:

Collections.addAll(list, arr);
Collections.shuffle(list);
cardsList.toArray(arr);

Antwoord 11

Random rnd = new Random();
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;
}

Trouwens, ik heb gemerkt dat deze code een ar.length - 1aantal elementen retourneert, dus als je array 5 elementen heeft, zal de nieuwe shuffled array 4 elementen hebben. Dit gebeurt omdat de for-lus i>0zegt. Als je verandert in i>=0, worden alle elementen geschud.


Antwoord 12

Hier is een algemene versie voor arrays:

import java.util.Random;
public class Shuffle<T> {
    private final Random rnd;
    public Shuffle() {
        rnd = new Random();
    }
    /**
     * Fisher–Yates shuffle.
     */
    public void shuffle(T[] ar) {
        for (int i = ar.length - 1; i > 0; i--) {
            int index = rnd.nextInt(i + 1);
            T a = ar[index];
            ar[index] = ar[i];
            ar[i] = a;
        }
    }
}

Aangezien ArrayList in feite slechts een array is, kan het raadzaam zijn om met een ArrayList te werken in plaats van de expliciete array en Collections.shuffle() te gebruiken. Prestatietests laten echter geen significant verschil zien tussen het bovenstaande en Collections.sort():

Shuffe<Integer>.shuffle(...) performance: 576084 shuffles per second
Collections.shuffle(ArrayList<Integer>) performance: 629400 shuffles per second
MathArrays.shuffle(int[]) performance: 53062 shuffles per second

De Apache Commons-implementatie MathArrays.shuffle is beperkt tot int[] en de prestatievermindering is waarschijnlijk te wijten aan het gebruik van de generator voor willekeurige getallen.


Antwoord 13

Hier is een oplossing die Apache Commons Math 3.x gebruikt (alleen voor int[]-arrays):

MathArrays.shuffle(array);

http://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/util/MathArrays.html#shuffle( int[])

Als alternatief introduceerde Apache Commons Lang 3.6 nieuwe shuffle-methoden voor de klasse ArrayUtils(voor objecten en elk primitief type).

ArrayUtils.shuffle(array);

http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/ArrayUtils.html#shuffle-int:A-


Antwoord 14

Ik zag wat ontbrekende informatie in sommige antwoorden, dus besloot ik een nieuwe toe te voegen.

Java-verzamelingen Arrays.asList neemt var-arg van het type T (T ...). Als u een primitieve array (int-array) doorgeeft, zal de asList-methode een List<int[]>afleiden en genereren, wat een lijst met één element is (het ene element is de primitieve array). als je deze lijst met één element door elkaar schudt, verandert er niets.

Dus u moet eerst uw primitieve array converteren naar Wrapper-objectarray. hiervoor kun je de ArrayUtils.toObjectmethode van apache.commons.lang gebruiken. geef de gegenereerde array vervolgens door aan een lijst en schud die ten slotte.

 int[] intArr = {1,2,3};
  List<Integer> integerList = Arrays.asList(ArrayUtils.toObject(array));
  Collections.shuffle(integerList);
  //now! elements in integerList are shuffled!

Antwoord 15

Hier is nog een manier om een lijst in willekeurige volgorde af te spelen

public List<Integer> shuffleArray(List<Integer> a) {
List<Integer> b = new ArrayList<Integer>();
    while (a.size() != 0) {
        int arrayIndex = (int) (Math.random() * (a.size()));
        b.add(a.get(arrayIndex));
        a.remove(a.get(arrayIndex));
    }
    return b;
}

Kies een willekeurig nummer uit de originele lijst en sla het op in een andere lijst. Verwijder vervolgens het nummer uit de originele lijst. De grootte van de originele lijst zal met één afnemen totdat alle elementen naar de nieuwe lijst zijn verplaatst.


Antwoord 16

Een eenvoudige oplossing voor Groovy:

solutionArray.sort{ new Random().nextInt() }

Hiermee worden alle elementen van de arraylijst willekeurig gesorteerd, waardoor het gewenste resultaat van het shuffelen van alle elementen wordt gearchiveerd.


Antwoord 17

Met behulp van Ints.asList()het is zo simpel als:

Collections.shuffle(Ints.asList(array));

Antwoord 18

De willekeurige klasse gebruiken

 public static void randomizeArray(int[] arr) {
      Random rGenerator = new Random(); // Create an instance of the random class 
      for (int i =0; i< arr.length;i++ ) {
          //Swap the positions...
          int rPosition = rGenerator.nextInt(arr.length); // Generates an integer within the range (Any number from 0 - arr.length)
          int temp = arr[i]; // variable temp saves the value of the current array index;
          arr[i] = arr[rPosition];  // array at the current position (i) get the value of the random generated 
          arr[rPosition] = temp; // the array at the position of random generated gets the value of temp
      }
      for(int i = 0; i<arr.length; i++) {
          System.out.print(arr[i]); //Prints out the array
      } 
  }

Antwoord 19

Ik weeg deze zeer populaire vraag af omdat niemand een shuffle-copy-versie heeft geschreven. Stijl is zwaar geleend van Arrays.java, want wie nietplundert tegenwoordig de Java-technologie? Generieke en intimplementaties inbegrepen.

  /**
    * Shuffles elements from {@code original} into a newly created array.
    *
    * @param original the original array
    * @return the new, shuffled array
    * @throws NullPointerException if {@code original == null}
    */
   @SuppressWarnings("unchecked")
   public static <T> T[] shuffledCopy(T[] original) {
      int originalLength = original.length; // For exception priority compatibility.
      Random random = new Random();
      T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), originalLength);
      for (int i = 0; i < originalLength; i++) {
         int j = random.nextInt(i+1);
         result[i] = result[j];
         result[j] = original[i];
      }
      return result;
   }
   /**
    * Shuffles elements from {@code original} into a newly created array.
    *
    * @param original the original array
    * @return the new, shuffled array
    * @throws NullPointerException if {@code original == null}
    */
   public static int[] shuffledCopy(int[] original) {
      int originalLength = original.length;
      Random random = new Random();
      int[] result = new int[originalLength];
      for (int i = 0; i < originalLength; i++) {
         int j = random.nextInt(i+1);
         result[i] = result[j];
         result[j] = original[i];
      }
      return result;
   }

Antwoord 20

Dit is knuth shuffle algoritme.

public class Knuth { 
    // this class should not be instantiated
    private Knuth() { }
    /**
     * Rearranges an array of objects in uniformly random order
     * (under the assumption that <tt>Math.random()</tt> generates independent
     * and uniformly distributed numbers between 0 and 1).
     * @param a the array to be shuffled
     */
    public static void shuffle(Object[] a) {
        int n = a.length;
        for (int i = 0; i < n; i++) {
            // choose index uniformly in [i, n-1]
            int r = i + (int) (Math.random() * (n - i));
            Object swap = a[r];
            a[r] = a[i];
            a[i] = swap;
        }
    }
    /**
     * Reads in a sequence of strings from standard input, shuffles
     * them, and prints out the results.
     */
    public static void main(String[] args) {
        // read in the data
        String[] a = StdIn.readAllStrings();
        // shuffle the array
        Knuth.shuffle(a);
        // print results.
        for (int i = 0; i < a.length; i++)
            StdOut.println(a[i]);
    }
}

Antwoord 21

Er is ook een andere manier, nog niet posten

//that way, send many object types diferentes
public anotherWayToReciveParameter(Object... objects)
{
    //ready with array
    final int length =objects.length;
    System.out.println(length);
    //for ready same list
    Arrays.asList(objects);
}

zo makkelijker, afhankelijk van de context


Antwoord 22

De meest eenvoudige oplossing voor dit willekeurig shuffelen in een array.

String location[] = {"delhi","banglore","mathura","lucknow","chandigarh","mumbai"};
int index;
String temp;
Random random = new Random();
for(int i=1;i<location.length;i++)
{
    index = random.nextInt(i+1);
    temp = location[index];
    location[index] = location[i];
    location[i] = temp;
    System.out.println("Location Based On Random Values :"+location[i]);
}

Antwoord 23

Eenvoudigste code om te shufflen:

import java.util.*;
public class ch {
    public static void main(String args[])
    {
        Scanner sc=new Scanner(System.in);
        ArrayList<Integer> l=new ArrayList<Integer>(10);
        for(int i=0;i<10;i++)
            l.add(sc.nextInt());
        Collections.shuffle(l);
        for(int j=0;j<10;j++)
            System.out.println(l.get(j));       
    }
}

Antwoord 24

  1. Boxvan int[]naar List<Integer>
  2. Shuffle met de methode Collections.shuffle
int[] solutionArray = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1 };
List<Integer> list = Arrays.stream(solutionArray).boxed().collect(Collectors.toList());
Collections.shuffle(list);
System.out.println(list.toString());
// [1, 5, 5, 4, 2, 6, 1, 3, 3, 4, 2, 6]

Antwoord 25

Je moet Collections.shuffle()gebruiken. U kunt echter niet rechtstreeks een reeks primitieve typen manipuleren, dus u moet een wrapper-klasse maken.

Probeer dit.

public static void shuffle(int[] array) {
    Collections.shuffle(new AbstractList<Integer>() {
        @Override public Integer get(int index) { return array[index]; }
        @Override public int size() { return array.length; }
        @Override public Integer set(int index, Integer element) {
            int result = array[index];
            array[index] = element;
            return result;
        }
    });
}

En

int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};
shuffle(solutionArray);
System.out.println(Arrays.toString(solutionArray));

uitvoer:

[3, 3, 4, 1, 6, 2, 2, 1, 5, 6, 5, 4]

Antwoord 26

public class ShuffleArray {
public static void shuffleArray(int[] a) {
    int n = a.length;
    Random random = new Random();
    random.nextInt();
    for (int i = 0; i < n; i++) {
        int change = i + random.nextInt(n - i);
        swap(a, i, change);
    }
}
private static void swap(int[] a, int i, int change) {
    int helper = a[i];
    a[i] = a[change];
    a[change] = helper;
}
public static void main(String[] args) {
    int[] a = new int[] { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1 };
    shuffleArray(a);
    for (int i : a) {
        System.out.println(i);
    }
}
}

Antwoord 27

import java.util.ArrayList;
import java.util.Random;
public class shuffle {
    public static void main(String[] args) {
        int a[] =  {1,2,3,4,5,6,7,8,9};
         ArrayList b = new ArrayList();
       int i=0,q=0;
       Random rand = new Random();
       while(a.length!=b.size())
       {
           int l = rand.nextInt(a.length);
//this is one option to that but has a flaw on 0
//           if(a[l] !=0)
//           {
//                b.add(a[l]);
//               a[l]=0;
//               
//           }
//           
// this works for every no. 
                if(!(b.contains(a[l])))
                {
                    b.add(a[l]);
                }
       }
//        for (int j = 0; j <b.size(); j++) {
//            System.out.println(b.get(j));
//            
//        }
System.out.println(b);
    }
}

Antwoord 28

vergelijkbaar zonder swap b te gebruiken

       Random r = new Random();
    int n = solutionArray.length;
    List<Integer> arr =  Arrays.stream(solutionArray).boxed().collect(Collectors.toList());
    for (int i = 0; i < n-1; i++) {
        solutionArray[i] = arr.remove( r.nextInt(arr.size())); // randomize base on size
    }
    solutionArray[n-1] = arr.get(0);

Antwoord 29

Een van de oplossingen is het gebruik van de permutatie om alle permutaties vooraf te berekenen en op te slaan in de ArrayList

Java 8 introduceerde een nieuwe methode, ints(), in de klasse java.util.Random. De methode ints() retourneert een onbeperkte stroom pseudowillekeurige int-waarden. U kunt de willekeurige getallen tussen een bepaald bereik beperken door de minimum- en maximumwaarden op te geven.

Random genRandom = new Random();
int num = genRandom.nextInt(arr.length);

Met behulp van het genereren van het willekeurige getal, kunt u de lus doorlopen en met de huidige index wisselen met het willekeurige getal..
Zo kun je een willekeurig getal genereren met O(1) ruimtecomplexiteit.


Antwoord 30

Zonder willekeurige oplossing:

  static void randomArrTimest(int[] some){
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < some.length; i++) {
            long indexToSwap = startTime%(i+1);
            long tmp = some[(int) indexToSwap];
            some[(int) indexToSwap] = some[i];
            some[i] = (int) tmp;
        }
        System.out.println(Arrays.toString(some));
    }

Other episodes