Jak randomizować dwie ArrayLists w ten sam sposób?


257

Mam dwie ArrayList filelisti imgListktóre powiązane ze sobą, na przykład „H1.txt” związane z „e1.jpg”. Jak automatycznie randomizować listę imgListwedług losowości fileList? Podobnie jak w programie Excel, jeśli posortujemy określoną kolumnę, druga kolumna automatycznie pojawi się za nią?

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);

wyjście po randomizacji np .:

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

planowana wydajność:

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

Odpowiedzi:


585

Użyj Collections.shuffle()dwa razy, z dwoma Randomobiektami zainicjowanymi tym samym ziarnem:

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

Użycie dwóch Randomobiektów z tym samym ziarnem gwarantuje, że obie listy zostaną przetasowane dokładnie w ten sam sposób. Pozwala to na dwie osobne kolekcje.


121

Zawiń je w inną klasę, abyś mógł otrzymać jedną tablicę lub Listte obiekty.

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

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

Przykład użycia:

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);

10
To jest obiektowe rozwiązanie Java. Być może, jak należy to zrobić ... :)
Evan

22

Najprostszym podejściem jest zamknięcie dwóch wartości razem w typ, który zawiera zarówno obraz, jak i plik. Następnie budować ArrayListz że i przetasować go.

Poprawia to również enkapsulację, zapewniając właściwość polegającą na tym, że zawsze będziesz mieć automatycznie taką samą liczbę plików jak obrazy.

Alternatywą, jeśli naprawdę nie podoba ci się ten pomysł, byłoby samodzielne napisanie kodu losowego (istnieje wiele przykładów zmodyfikowanego losowania Fisher-Yates w Javie, w tym kilka podejrzewanych o przepełnienie stosu) i po prostu operowanie na obu listach w o tym samym czasie. Ale zdecydowanie zalecam stosowanie podejścia „poprawa enkapsulacji”.


11

Możesz to zrobić za pomocą map:

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

Spowoduje to iterację obrazów w losowej kolejności.


5

Można to zrobić przy użyciu metody losowej:

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

4

Zamiast mieć dwie tablice ciągów, miej jedną tablicę niestandardowej klasy, która zawiera dwa ciągi.


3

Możesz utworzyć tablicę zawierającą liczby od 0 do 5 i przetasować je. Następnie użyj wyniku jako mapowania „oldIndex -> newIndex” i zastosuj to mapowanie do obu oryginalnych tablic.


2

Nie do końca wiem, co rozumiesz przez „automatycznie” - możesz utworzyć obiekt kontenerowy, który pomieści oba obiekty:

klasa publiczna FileImageHolder {String fileName; Ciąg imageName; // TODO: wstaw tutaj rzeczy}

A następnie umieść to na liście tablic i losowo tę listę tablic.

W przeciwnym razie musisz śledzić, gdzie każdy element porusza się na jednej liście, a także przenosić go na drugim.


2

Jeśli nie ma sposobu na odzyskanie starego indeksu elementów po ich przetasowaniu, zrobiłbym to na dwa sposoby:

A) Utwórz kolejną listę multi_shuffler = [0, 1, 2, ..., file.size ()] i potasuj ją. Pętlę nad nim, aby uzyskać porządek dla przetasowanych list plików / obrazów.

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

lub B) Utwórz klasę StringWrapper do przechowywania nazw plików / obrazów i połącz dwie listy, które już masz w jedną: ArrayList CombinedList;

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.