Skip to content

Commit

Permalink
Refactor "RandomSubset" internals for DRY, removing closure
Browse files Browse the repository at this point in the history
This is a squashed merge of PR #1049.

---------

Co-authored-by: Atif Aziz <code@raboof.com>
  • Loading branch information
viceroypenguin and atifaziz authored Nov 19, 2023
1 parent a0f72ab commit 3de8b3f
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 12 deletions.
11 changes: 5 additions & 6 deletions MoreLinq/RandomSubset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,25 @@ public static IEnumerable<T> RandomSubset<T>(this IEnumerable<T> source, int sub
if (source == null) throw new ArgumentNullException(nameof(source));
if (subsetSize < 0) throw new ArgumentOutOfRangeException(nameof(subsetSize));

return RandomSubsetImpl(source, rand, seq => (seq.ToArray(), subsetSize));
return RandomSubsetImpl(source, rand, subsetSize);
}

static IEnumerable<T> RandomSubsetImpl<T>(IEnumerable<T> source, Random rand, Func<IEnumerable<T>, (T[], int)> seeder)
static IEnumerable<T> RandomSubsetImpl<T>(IEnumerable<T> source, Random rand, int? subsetSize)
{
// The simplest and most efficient way to return a random subset is to perform
// an in-place, partial Fisher-Yates shuffle of the sequence. While we could do
// a full shuffle, it would be wasteful in the cases where subsetSize is shorter
// than the length of the sequence.
// See: http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

var (array, subsetSize) = seeder(source);
var array = source.ToArray();
subsetSize ??= array.Length;

if (array.Length < subsetSize)
{
#pragma warning disable CA2208 // Instantiate argument exceptions correctly
// TODO Throw InvalidOperationException instead?
// TODO Throw InvalidOperationException instead?
throw new ArgumentOutOfRangeException(nameof(subsetSize),
"Subset size must be less than or equal to the source length.");
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
}

var m = 0; // keeps track of count items shuffled
Expand Down
7 changes: 1 addition & 6 deletions MoreLinq/Shuffle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ namespace MoreLinq
{
using System;
using System.Collections.Generic;
using System.Linq;

public static partial class MoreEnumerable
{
Expand Down Expand Up @@ -70,11 +69,7 @@ public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rand)
if (source == null) throw new ArgumentNullException(nameof(source));
if (rand == null) throw new ArgumentNullException(nameof(rand));

return RandomSubsetImpl(source, rand, seq =>
{
var array = seq.ToArray();
return (array, array.Length);
});
return RandomSubsetImpl(source, rand, subsetSize: null);
}
}
}

0 comments on commit 3de8b3f

Please sign in to comment.