Перемешать любой (I)List
с использованием метода расширения, основанного на Shisherle Fisher-Yates :
private static Random rng = new Random();
public static void Shuffle(this IList list)
{
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
Использование:
List products = GetProducts();
products.Shuffle();
код выше использует сильно критикуемый метод System.Random для выбора кандидатов подкачки. Это быстро, но не так произвольно, как должно быть. Если вам нужно лучшее качество случайности в ваших тасованиях, используйте генератор случайных чисел в System.Security.Cryptography следующим образом:
using System.Security.Cryptography;
...
public static void Shuffle(this IList list)
{
RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
byte[] box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
В этом блоге доступно простое сравнение (WayBack Machine).
Редактирование: поскольку я пишу этот ответ пару лет назад, многие люди комментировали или писали мне, чтобы указать на большой глупый недостаток в моем сравнении. Они, конечно, правы. Нет ничего плохого в System.Random, если он используется так, как он был предназначен. В моем первом примере выше я создаю экземпляр rng-переменной внутри метода Shuffle, который запрашивает проблемы, если метод будет вызываться повторно. Ниже приведен фиксированный полный пример, основанный на действительно полезном комментарии, полученном сегодня от @weston здесь, на SO.
Program.cs:
using System;
using System.Collections.Generic;
using System.Threading;
namespace SimpleLottery
{
class Program
{
private static void Main(string[] args)
{
var numbers = new List(Enumerable.Range(1, 75));
numbers.Shuffle();
Console.WriteLine("The winning numbers are: {0}", string.Join(", ", numbers.GetRange(0, 5)));
}
}
public static class ThreadSafeRandom
{
[ThreadStatic] private static Random Local;
public static Random ThisThreadsRandom
{
get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
}
}
static class MyExtensions
{
public static void Shuffle(this IList list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}
var res = [[{Timestamp: "2019-01-15T08:26:00.000Z", Average: 200},
{Timestamp: "2019-01-15T08:32:00.000Z", Average: 200},
{Timestamp: "2019-01-15T08:26:00.000", Average: 200},
{Timestamp: "2019-01-15T08:29:00.000Z", Average: 200},
{Timestamp: "2019-01-15T08:35:00.000Z", Average: 200}],
[{Timestamp: "2019-01-15T08:26:00.000Z", Average: 400},
{Timestamp: "2019-01-15T08:32:00.000Z", Average: 400},
{Timestamp: "2019-01-15T08:26:00.000Z", Average: 400},
{Timestamp: "2019-01-15T08:29:00.000Z", Average: 200},
{Timestamp: "2019-01-15T08:35:00.000Z", Average: 200}]];
/* SECOND COMPILATION
[[{Timestamp: 2019-01-15T08:26:00.000Z, Average: 200},
{Timestamp: 2019-01-15T08:32:00.000Z, Average: 200},
{Timestamp: 2019-01-15T08:26:00.000, Average: 200},
{Timestamp: 2019-01-15T08:29:00.000Z, Average: 200},
{Timestamp: 2019-01-15T08:35:00.000Z, Average: 200}],
[{Timestamp: 2019-01-15T08:26:00.000Z, Average: 400},
{Timestamp: 2019-01-15T08:32:00.000Z, Average: 200},
{Timestamp: 2019-01-15T08:26:00.000, Average: 200},
{Timestamp: 2019-01-15T08:29:00.000Z, Average: 200},
{Timestamp: 2019-01-15T08:35:00.000Z, Average: 200}]] */
let results = res.reduce((acc,resArray) => {
innerResult = resArray.reduce((_acc,obj) => {
if(obj.Average == 200) {
_acc.up++;
} else {
_acc.down++;
_acc.time = obj.Timestamp;
}
return _acc;
}, { up:0, down:0, time:null });
if(innerResult.up > innerResult.down) {
acc.res.push('up');
acc.ts.push(null);
}
else {
acc.res.push('down');
acc.ts.push(innerResult.time);
}
return acc;
}, {res:[], ts:[]});
console.log(results.res);
console.log(results.ts);