Bagaimana cara mengacak dua ArrayLists dengan cara yang sama?

257

Saya memiliki dua daftar array filelistdan imgListyang terkait satu sama lain, misalnya "H1.txt" yang terkait dengan "e1.jpg". Bagaimana cara secara acak daftar imgListsesuai dengan pengacakanfileList ? Seperti di excel, jika kita mengurutkan kolom tertentu, kolom lainnya akan secara otomatis mengikuti?

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

output setelah pengacakan misalnya:

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

hasil yang diinginkan:

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

Jawaban:

585

Gunakan Collections.shuffle()dua kali, dengan dua Randomobjek diinisialisasi dengan seed yang sama:

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

Menggunakan dua Randomobjek dengan seed yang sama memastikan bahwa kedua daftar akan dikocok dengan cara yang persis sama. Ini memungkinkan untuk dua koleksi terpisah.

Michael Borgwardt
sumber
121

Bungkus mereka di kelas lain sehingga Anda bisa berakhir dengan satu array atau Listobjek-objek itu.

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

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

Contoh penggunaan:

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
sumber
10
Ini adalah Java, solusi berorientasi objek. Mungkin, bagaimana hal itu harus dilakukan ... :)
Evan
22

Pendekatan paling sederhana adalah merangkum kedua nilai tersebut bersama-sama menjadi tipe yang memiliki gambar dan file. Kemudian membangun ArrayListdari yang dan mengocok itu.

Itu meningkatkan enkapsulasi juga, memberi Anda properti yang Anda akan selalu memiliki jumlah file yang sama dengan gambar secara otomatis.

Alternatif jika Anda benar - benar tidak menyukai gagasan itu adalah menulis sendiri kode shuffle (ada banyak contoh shuffle Fisher-Yates yang dimodifikasi di Jawa, termasuk beberapa di Stack Overflow yang saya duga) dan hanya beroperasi pada kedua daftar di waktu yang sama. Tapi saya sangat merekomendasikan pergi dengan pendekatan "meningkatkan enkapsulasi".

Jon Skeet
sumber
11

Anda bisa melakukan ini dengan peta:

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

Ini akan beralih melalui gambar dalam urutan acak.

jjnguy
sumber
5

Ini dapat dilakukan dengan menggunakan metode acak:

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
sumber
4

Alih-alih memiliki dua larik String, miliki satu larik kelas khusus yang berisi dua string Anda.

EboMike
sumber
3

Anda bisa membuat larik yang berisi angka 0 hingga 5 dan mengocoknya. Kemudian gunakan hasilnya sebagai pemetaan "oldIndex -> newIndex" dan terapkan pemetaan ini untuk kedua array asli Anda.

Mark Byers
sumber
2

Tidak sepenuhnya yakin apa yang Anda maksud dengan "secara otomatis" - Anda dapat membuat objek penampung yang menampung kedua objek:

FileImageHolder {String fileName kelas publik; String imageName; // TODO: masukkan barang di sini}

Dan kemudian memasukkannya ke dalam daftar array dan mengacak daftar array itu.

Jika tidak, Anda perlu melacak di mana setiap elemen bergerak dalam satu daftar, dan memindahkannya di yang lain juga.

aperkins
sumber
2

Kecuali jika ada cara untuk mengambil indeks elemen yang lama setelah mereka dikocok, saya akan melakukannya dengan satu dari dua cara:

A) Buat daftar lain multi_shuffler = [0, 1, 2, ..., file.size ()] dan kocok. Lingkari untuk mendapatkan urutan daftar file / gambar yang diacak.

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

atau B) Buat kelas StringWrapper untuk menampung nama file / gambar dan menggabungkan dua daftar yang sudah Anda miliki menjadi satu: ArrayList gabungan Daftar;

ajwood
sumber