Як рандомізувати два ArrayListe однаково?


257

У мене є два ArrayList filelistі imgListякі пов'язані один з одним, наприклад , «H1.txt» , пов'язані з «e1.jpg». Як автоматично рандомізувати список imgListзгідно рандомізації fileList? Як у excel, якщо ми відсортуємо певний стовпець, інший стовпець автоматично буде слідувати?

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

вихід після рандомізації, наприклад:

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

передбачуваний вихід:

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

Відповіді:


585

Використовуйте Collections.shuffle()двічі з двома Randomоб'єктами, ініціалізованими з одним і тим же насінням:

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

Використання двох Randomоб'єктів з однаковим насінням гарантує, що обидва списки будуть змішуватися точно однаково. Це дозволяє отримати дві окремі колекції.


121

Загорніть їх в інший клас, щоб ви могли одержати один масив або Listці об’єкти.

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

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

Приклад використання:

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
Це Java, об'єктно-орієнтоване рішення. Можливо, як це слід робити ... :)
Еван

22

Найпростіший підхід - це інкапсуляція двох значень разом у тип, який має і зображення, і файл. Потім складіть ArrayListз цього і перемістіть його.

Це також покращує інкапсуляцію, надаючи властивість, що у вас завжди буде однакова кількість файлів, що і зображення автоматично.

Альтернативою, якщо вам дійсно не подобається ця ідея, було б написати код перетасовки самостійно (є багато прикладів модифікованих перетасовок Fisher-Yates на Java, включаючи декілька на переповнення стека, я підозрюю) і просто працювати в обох списках на одночасно. Але я настійно рекомендую перейти до «поліпшення інкапсуляції».


11

Це можна зробити за допомогою карт:

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

Це повторить зображення у випадковому порядку.


5

Це можна зробити за допомогою методу перетасування:

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

Замість того, щоб мати два масиви Strings, майте один масив користувацького класу, який містить дві ваші рядки.


3

Ви можете створити масив, що містить числа від 0 до 5, і перемістити їх. Потім використовуйте результат як відображення "oldIndex -> newIndex" і застосуйте це відображення до обох початкових масивів.


2

Не зовсім впевнений, що ви розумієте під "автоматично" - ви можете створити контейнерний об'єкт, який містить обидва об'єкти:

публічний клас FileImageHolder {String fileName; String imageName; // TODO: сюди вставляйте речі}

А потім помістіть це у список масиву та рандомізуйте цей список масивів.

В іншому випадку вам потрібно буде відслідковувати, куди кожен елемент перемістився в одному списку, а також перемістити його в інший.


2

Якщо немає способу отримати старий індекс елементів після їх перемішування, я б це зробив одним із двох способів:

A) Складіть інший список multi_shuffler = [0, 1, 2, ..., file.size ()] і перемістіть його. Прокрутіть її, щоб отримати замовлення для перетасованих списків файлів / зображень.

ArrayList newFileList = новий ArrayList (); ArrayList newImgList = новий ArrayList (); для (i = 0; i

або B) Складіть клас StringWrapper, щоб містити імена файлів / зображень та об'єднати два списки, які ви вже потрапили в один: ArrayList unitedList;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.