Working on a current project, had a need to do this. It’s a pretty brute-force way of doing things because frankly, I’m not a brainiac :)
Interested in what my readers think.
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> collection)
{
var r = new Random();
var enumerable = collection as T[] ?? collection.ToArray();
int numItems = enumerable.Count();
// Create a new spot to put 'em
var retVal = new T[numItems];
// Know which ones we've put in
var addedIndices = new int[numItems];
for (int i = 0; i < numItems; i++)
{
if (i == numItems - 1)
{ // Last item, don't waste any time just pick the last one available
retVal[i] = enumerable.Except(retVal).First();
}
else
{
// Pick one from the source that we haven't picked yet
int chosenIndex;
do
{
chosenIndex = r.Next(numItems);
} while (addedIndices.Contains(chosenIndex));
retVal[i] = enumerable[chosenIndex];
addedIndices[i] = chosenIndex;
}
}
return retVal;
}