Перемешать два списка одинаково - PullRequest
1 голос
/ 15 марта 2012

Я хочу перетасовать два списка, чтобы они были перетасованы одинаково (при условии, что у меня есть метод Shuffle (Список списков), который перетасовывает один список.

List<ObjX> listA = new List<ObjX>() { A, B, C, D };
List<ObjX> listB = new List<ObjX>() { W, X, Y, Z };
ShuffleTwoLists(listA , listB )

Результат:
A: C, B, D, A
B: Y, X, Z, W

Существует ли быстрый способ реализации списков ShuffleTwoLists (listA, listB) в C #?

Ответы [ 3 ]

8 голосов
/ 15 марта 2012

Вариант 1: zip, shuffle, unzip

Чтобы расширить комментарий Марсело, и предположим, что вы не против создать новые списки вместо перетасовки существующих списков:

var zipped = listA.Zip(listB, (a, b) => new { a, b } ).ToList();
Shuffle(zipped);
var newListA = zipped.Select(pair => pair.a).ToList();
var newListB = zipped.Select(pair => pair.b).ToList();

Вариант 2: перетасовать индексы

Расширить ответ MAK с помощью кода:

var indexes = Enumerable.Range(0, listA.Count).ToList();
Shuffle(indexes);
var newListA = indexes.Select(index => listA[index]).ToList();
var newListB = indexes.Select(index => listB[index]).ToList();

Конечно, оба подхода могут видоизменить исходные списки, с немного большей работой.

Вариант 3: перемешать оба списка одним и тем же случайным начальным числом

Лично мне нравится передавать Random (или что-то еще) в методы / классы, которые нуждаются в них вместо создания новых. Поэтому я бы дал свой параметр Shuffle a Random. Это позволяет избежать различных проблем и хорошо выражает зависимость. Вы можете использовать это в своих интересах, создав два Random экземпляра с одинаковым начальным числом:

int seed = existingRandom.Next();
Shuffle(listA, new Random(seed));
Shuffle(listB, new Random(seed));

Если предположить, что Shuffle делает то же самое, если задана одна и та же последовательность случайных чисел, это перетасует оба списка одинаково.

5 голосов
/ 15 марта 2012

Все техники Джона хороши.Дополнительный прием:

class PermutedList<T> 
{
    private readonly IList<T> underlying;
    private readonly IList<int> permutation;
    public T this[int i]
    {
        get { return underlying[permutation[i]]; }
    }
    ...

То есть создайте класс-оболочку вокруг базового списка.Сделайте перестановку, перетасовывая массив с номерами от 0 до n-1.Если вы примените один и тот же массив перестановок к двум разным спискам, то вы получите одинаковое «перемешивание» двух разных списков.Имеет смысл?

2 голосов
/ 15 марта 2012

Возьмите новый список целых чисел, содержимое которых содержит все числа в [0, length of A and B).Они соответствуют индексам элементов в ваших списках.Перемешать этот список.Теперь переставьте оба ваших исходных списка, используя перетасованные индексы.

...