Comment randomiser deux ArrayLists de la même manière?

257

J'ai deux arraylist filelistet imgListqui sont liés les uns aux autres, par exemple "H1.txt" lié à "e1.jpg". Comment randomiser automatiquement la liste en imgListfonction de la randomisation de fileList? Comme dans Excel, si nous trions certaines colonnes, l'autre colonne suivra automatiquement?

String [] file = {"H1.txt","H2.txt","H3.txt","M4.txt","M5.txt","M6.txt"};
ArrayList<String> fileList = new ArrayList<String>(Arrays.asList(file));

String [] img = {"e1.jpg","e2.jpg","e3.jpg","e4.jpg","e5.jpg","e6.jpg"};
ArrayList<String> imgList = new ArrayList<String>(Arrays.asList(img));

//randomized files
Collections.shuffle(fileList);

sortie après randomisation par exemple:

fileList = {"M4.txt","M6.txt","H3.txt","M5.txt","H2.txt","H1.txt"};

sortie prévue:

 imgList = {"e4.jpg","e6.jpg","e3.jpg","e5.jpg","e2.jpg","e1.jpg"};
Jessy
la source

Réponses:

585

Utilisez Collections.shuffle()deux fois, avec deux Randomobjets initialisés avec la même graine:

long seed = System.nanoTime();
Collections.shuffle(fileList, new Random(seed));
Collections.shuffle(imgList, new Random(seed));

L'utilisation de deux Randomobjets avec la même graine garantit que les deux listes seront mélangées exactement de la même manière. Cela permet deux collections distinctes.

Michael Borgwardt
la source
121

Enveloppez-les dans une autre classe afin que vous puissiez vous retrouver avec un seul tableau ou Listde ces objets.

public class Data {
    private String txtFileName;
    private String imgFileName;

    // Add/generate c'tor, getter/setter, equals, hashCode and other boilerplate.
}

Exemple d'utilisation:

List<Data> list = new ArrayList<Data>();
list.add(new Data("H1.txt", "e1.jpg"));
list.add(new Data("H2.txt", "e2.jpg"));
// ...

Collections.shuffle(list);
BalusC
la source
10
Ceci est la solution orientée objet Java. Peut-être, comment cela devrait être fait ... :)
Evan
22

L'approche la plus simple consiste à encapsuler les deux valeurs ensemble dans un type contenant à la fois l'image et le fichier. Ensuite , construire un ArrayListde qui et mélangez.

Cela améliore également l'encapsulation, vous donnant la propriété que vous aurez toujours le même nombre de fichiers que d'images automatiquement.

Une alternative si vous n'aimez vraiment pas cette idée serait d'écrire le code de shuffle vous-même (il existe de nombreux exemples de shuffle Fisher-Yates modifié en Java, dont plusieurs sur Stack Overflow je suppose) et de simplement opérer sur les deux listes à le même temps. Mais je recommanderais fortement de suivre l'approche "améliorer l'encapsulation".

Jon Skeet
la source
11

Vous pouvez le faire avec des cartes:

Map<String, String> fileToImg:
List<String> fileList = new ArrayList(fileToImg.keySet());
Collections.shuffle(fileList);
for(String item: fileList) {
    fileToImf.get(item);
}

Cela parcourra les images dans un ordre aléatoire.

jjnguy
la source
5

Cela peut être fait en utilisant la méthode aléatoire:

private List<Integer> getJumbledList() {
     List<Integer> myArrayList2 = new ArrayList<Integer>();
        myArrayList2.add(8);
        myArrayList2.add(4);
        myArrayList2.add(9);
        Collections.shuffle(myArrayList2);
        return myArrayList2;
Rohit Goyal
la source
4

Au lieu d'avoir deux tableaux de chaînes, ayez un tableau d'une classe personnalisée qui contient vos deux chaînes.

EboMike
la source
3

Vous pouvez créer un tableau contenant les nombres 0 à 5 et les mélanger. Utilisez ensuite le résultat comme un mappage de "oldIndex -> newIndex" et appliquez ce mappage à vos deux tableaux d'origine.

Mark Byers
la source
2

Vous ne savez pas exactement ce que vous entendez par "automatiquement" - vous pouvez créer un objet conteneur qui contient les deux objets:

classe publique FileImageHolder {String fileName; String imageName; // TODO: insérer des trucs ici}

Et puis mettez cela dans une liste de tableaux et randomisez cette liste de tableaux.

Sinon, vous devrez garder une trace de l'endroit où chaque élément a été déplacé dans une liste, et le déplacer également dans l'autre.

aperkins
la source
2

À moins qu'il n'y ait un moyen de récupérer l'ancien index des éléments après qu'ils ont été mélangés, je le ferais de deux manières:

A) Créez une autre liste multi_shuffler = [0, 1, 2, ..., file.size ()] et mélangez-la. Faites une boucle dessus pour obtenir l'ordre de vos listes de fichiers / images mélangées.

ArrayList newFileList = new ArrayList (); ArrayList newImgList = new ArrayList (); pour (i = 0; i

ou B) Créez une classe StringWrapper pour contenir les noms de fichier / image et combinez les deux listes que vous avez déjà en une seule: ArrayList combineList;

ajwood
la source