2

How can I randomize arrayList so that old index must not be the same as new index for all elements

for example with a list with 3 items

after arrayList randomize

old index<->new index

1<-->2 <--different
2<-->1 <--different
3<-->3 <--same is not allowed

I want to make sure it will be

1<-->3 <--different
2<-->1 <--different
3<-->2 <--different
Tse Ka Leong
  • 408
  • 4
  • 20
  • Are you sure you want to randomize? I think having constraints rules out randomness. Or simply to rearrange? If so u can simply reassign to `(index+n) % array.length` where n is any number. – Sach Dec 04 '14 at 06:56
  • Funny how some OPs seemingly disappear about 30 seconds after they just spent 10 minutes posting a question... ;) – Jan Groth Dec 04 '14 at 07:17
  • http://stackoverflow.com/questions/4228975/how-to-randomize-arraylist http://stackoverflow.com/questions/9701639/is-collections-shuffle-really-random-enough-practical-examples-seem-to-deny-t – Ian2thedv Dec 04 '14 at 07:19
  • this just make sure two array random in the same way with same seed. even with two different seeds, it may have the chance to get the same value. – Tse Ka Leong Dec 04 '14 at 07:42

4 Answers4

4
Collections.shuffle(List<?> list)

This should work with Lists which don't contain null values:

static <T> void shuffleList(List<T> list) {
    List<T> temp = new ArrayList<T>(list);
    Random rand = new Random();

    for (int i = 0; i < list.size(); i++) {
        int newPos = rand.nextInt(list.size());
        while (newPos == i||temp.get(newPos)==null) {
            newPos = rand.nextInt(list.size());
        }
        list.set(i, temp.get(newPos));
        temp.set(newPos,null);
    }
}

For list with null values:

static <T> void shuffleList(List<T> list) {
    List<T> temp = new ArrayList<T>(list);
    Integer [] indexes=new Integer[list.size()];
    for (int i=0;i<list.size();i++){
        indexes[i]=i;
    }
    Random rand = new Random();

    for (int i = 0; i < list.size(); i++) {
        int newPos = rand.nextInt(list.size());
        while (newPos == i||indexes[newPos]==null) {
            newPos = rand.nextInt(list.size());
        }
        list.set(i, temp.get(newPos));
        indexes[newPos]=null;
    }
}
Tkachuk_Evgen
  • 1,334
  • 11
  • 17
  • 2
    I don't think that's correct, as it does not guarantee that each elements ends up in a new position. – Jan Groth Dec 04 '14 at 07:05
  • Nope, I'm wrong. It is correct. Your explanation is a bit sparse though. – Jan Groth Dec 04 '14 at 07:07
  • According to the question it is not correct. OP wants all elements to be in different positions. This does not guarantee this. – Ian2thedv Dec 04 '14 at 07:09
  • _This implementation traverses the list backwards, from the last element up to the second, repeatedly swapping a randomly selected element into the "current position". Elements are randomly selected from the portion of the list that runs from the first element to the current position, inclusive._ from here: https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle – Jan Groth Dec 04 '14 at 07:12
  • Well I just ran it about twice, with the values OP provided and `2` did not move from it's original position. This answer suggests doing it twice with random `seeds`: http://stackoverflow.com/questions/4228975/how-to-randomize-arraylistv – Ian2thedv Dec 04 '14 at 07:20
  • Your answer is looping through the whole array and get new random position and check if new index is same as old index. but in my example, at third iteration, the only position left is 3 There is no way to get another position,then the while loop will.. – Tse Ka Leong Dec 04 '14 at 08:20
  • finally, i do it by shuffle the list and check all element after shuffle and re-shuffle it until all index are all changed. – Tse Ka Leong Dec 05 '14 at 08:39
  • use this code `long seed = System.nanoTime(); Collections.shuffle(fileList, new Random(seed));` – Mohammad No3ratii Jun 25 '22 at 06:49
2

That's something you have to implement yourself.

  • The shuffle is probably a series of random swaps (e.g. swap 1 -> 4, swap 3 -> 2).
  • Keep track of each element's new position (e.g. 4 3 2 1 5 for a list with 5 elements and the above shuffle operations).
  • If any element is still at it's old place (5 in that example), keep on shuffling.

Sounds like fun.

Jan Groth
  • 14,039
  • 5
  • 40
  • 55
0
var numExist = [];
while(numExist.length!=array.length){
  var randomizer = new Random();
  int i =0;
  var num = randomizer.nextInt(array.length);
  if(!numExist.contains(num)){
    array[i]=array[num];
    numExist.add(num);
    i++;
  }
}
  • 1
    Code dumps without any explanation are rarely helpful. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please [edit] your question and explain how it works better than what the OP provided. – ChrisGPT was on strike Dec 16 '19 at 03:07
0

The following is a variation of Fisher-Yates which caters to the possibility that at least one item will remain in its original position.

The current Collections.shuffle() does not perform a complete randomization of the list.

   public static void shuffle(List<Integer> list) {
      Random r = new Random();
      int size = list.size();
      boolean flag = true;
      for (int i = size - 1; i >= 0 && flag; i--) {
         int pos = r.nextInt(i + 1);
         if (list.get(i) == pos) {
            if (i == 0) {
               flag = false;
               break;
            }
            // counter the upcoming decrement by incrementing i
            i++;
            continue;
         }
         int temp = list.get(i);
         list.set(i, list.get(pos));
         list.set(pos, temp);
      }

// At this juncture, list.get(0) points to itself so choose a random candidate
// and swap them.

      if (!flag) {
         int pos = r.nextInt(size - 1) + 1;
         int temp = list.get(0);
         list.set(0, list.get(pos));
         list.set(pos, list.get(0));
      }
   }

There may still be eventual problems but I used the following code to test the shuffle with no problems detected.

      for (int k = 0; k < 100000; k++) {
         List<Integer> list =
               IntStream.range(0, 52).boxed().collect(Collectors.toList());
         System.out.println("Test run #" + k);
         // Collections.shuffle(list);
         shuffle(list);
         for (int i = 0; i < list.size(); i++) {
            if (i == list.get(i)) {
               System.out.printf("Oops! List.get(%d) == %d%n", list.get(i), i);
            }
         }
      }

WJS
  • 36,363
  • 4
  • 24
  • 39