Reputation: 91
I have two string lists en
and en1
List<string> en = new List<string>(new string[] { "horse", "cat", "dog", "milk", "honey"});
List<string> en1 = new List<string>(new string[] { "horse1", "cat2", "dog3", "milk4", "honey5" });
And I want radomize their content "Shuffle them" and put this radomized content to new two lists. But I also want them randomize same way so lists after randomization will still be
en[0] == en1[0]
random content after randomization
{ "cat", "horse", "honey", "milk", "dog"}
{ "cat2", "horse1", "honey5", "milk4", "dog3"}
Upvotes: 3
Views: 833
Reputation: 9772
Third obvious way:
Shuffle a list of integers 0, 1, ... , Count-1
and use this list as indexes into the original lists.
This goes along this lines (for user38...):
List<int> shuffeledIndex = new List<int>();
for(int i = 0; i < en.Count; i++) shuffeledIndex.Add(i);
shuffeledIndex.Shuffle(); // Assume this exists
enshuffeled = en[shuffeledIndex[i]]; // instead en[i]
en1shuffeled = en1[shuffeledIndex[i]];
Upvotes: 4
Reputation: 10756
Adding to Jon Skeet's answer, a nice way to do the shuffling is OrderBy(x => Guid.NewGuid())
so the code would look like
var joined = en.Zip(en1, (x, y) => new { x, y });
var shuffled = joined.OrderBy(x => Guid.NewGuid()).ToList();
en = shuffled.Select(pair => pair.x).ToList();
en1 = shuffled.Select(pair => pair.y).ToList();
Upvotes: 3
Reputation: 2001
You could first combine the two lists into one using the Zip function:
var zipped = en.Zip(en1, (first, second) => new { first, second }).ToList();
You'll then need a shuffling function to shuffle them. You could use the Fisher–Yates shuffle in an extension method:
public static void FisherYatesShuffle<T>(this IList<T> list)
{
var rnd = new Random();
var x = list.Count;
while (x > 1) {
x--;
var y = rnd.Next(x + 1);
T value = list[y];
list[y] = list[x];
list[x] = value;
}
}
To use the extension method:
var shuffled = zipped.FisherYatesShuffle();
Now you can split them back out again into two separate lists:
en = shuffled.Select(combined => combined.x).ToList();
en1 = shuffled.Select(combined => combined.y).ToList();
Upvotes: 0
Reputation: 6002
Well, I think @Jon Skeet's answer is better than mine (since I only know the basics about C# and probably for some other reasons... :P), however you could shuffle your lists manually with something like this:
for(int i=0;i<en.Count;i++) {
int remainingCount = en.Count - 1;
int exchangeIndex = i + (new Random()).nextInt(0, remainingCount);
swap(en, i, exchangeIndex);
swap(en1, i, exchangeIndex);
}
Of course you would need to write a swap function like swap(List<string> list, int indexA, int indexB)
:
string tmp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = tmp;
Upvotes: 0
Reputation: 1499840
Two obvious ways:
The second sounds cleaner to me. You'd use something like:
var joined = en.Zip(en1, (x, y) => new { x, y }).ToList();
var shuffled = joined.Shuffle(); // Assume this exists
en = shuffled.Select(pair => pair.x).ToList();
en1 = shuffled.Select(pair => pair.y).ToList();
Upvotes: 4