Last active
July 9, 2020 12:05
-
-
Save yKimisaki/f608a52cd4f11cf2150235df2dae775f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Tonari.Linq | |
{ | |
public static class ReadOnlyListExtensions | |
{ | |
private static Random Random = new Random(); | |
// あらかじめ1~必要数ぐらいの数列をキャッシュ | |
private const int LinedIntegersLength = 1024; | |
private static int[] LinedIntegersCache; | |
static ReadOnlyListExtensions() | |
{ | |
LinedIntegersCache = new int[LinedIntegersLength]; | |
for (int i = 0; i < LinedIntegersLength; i++) LinedIntegersCache[i] = i; | |
} | |
public static int[] CreateAndShuffleLinedIntegers(int length) | |
{ | |
// 毎度生成じゃなくて、キャッシュから丸っとコピーして速度を稼ぐ | |
var values = new int[length]; | |
Buffer.BlockCopy(LinedIntegersCache, 0, values, 0, length * sizeof(int)); | |
void Swap(int[] array, int left, int right) | |
{ | |
var temp = array[left]; | |
array[left] = array[right]; | |
array[right] = temp; | |
} | |
// 入れ替えずとも最後の1個は確定してるからその手前で抜ける | |
while (length > 2) | |
{ | |
--length; | |
// ランダムに持ってきて最後と入れ替える | |
// 次のループでlengthが1減るので最後がランダムに判定に入らず確定 | |
Swap(values, Random.Next(length), length); | |
} | |
return values; | |
} | |
public static IEnumerable<T> Shuffle<T>(this IReadOnlyList<T> source) | |
{ | |
foreach (var index in CreateAndShuffleLinedIntegers(source.Count)) | |
yield return source[index]; | |
} | |
public static T SampleOne<T>(this IReadOnlyList<T> source) | |
{ | |
return source[Random.Next(source.Count)]; | |
} | |
public static T SampleOne<T>(this IReadOnlyList<T> source, Predicate<T> predicate) | |
{ | |
foreach (var element in Shuffle(source)) | |
{ | |
if (predicate(element)) | |
return element; | |
} | |
return default; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment