2012-02-20 4 views
3

я получил IEnumerable коллекции следующегослучайный порядок из IEnumerable

var result1 = GetResult1() // Returns 2,4,5,6 

я должен жонглировать элементы и создать еще одну коллекцию в случайном порядке, которое должно привести к следующему образом:

var result2 = GetResult2(result1) // Returns 2,4,5,6 in a random order. 
// An example output would be 4,6,2,5 in the resultant collection. 

Я сделал это следующим образом:

var result1 = GetResult1(); 
var random = new Random(); 
var result2 = result1.OrderBy(order=>random.Next()); 

Однако проблема заключается в том, что если я acc ess result2 элементы в result2 снова перетасовываются, т. е. если я дважды выводят результаты результата2 на консоль, элементы снова жонглируются.

Не могли бы вы посоветоваться, как сохранить эту форму. когда я жонглирую коллекцию, она должна оставаться такой же, как и в дальнейшем. Я должен использовать ленивую оценку, потому что результаты очень большие по размеру.

ответ

1

Я вижу, вам требуется ленивые вычисления для результатов, если это так, то вы можете сделать это:

var randomNumbers = result1.Select(r => random.Next()).ToArray(); 
var orderedResult = result1.Zip(randomNumbers, (r, o) => new { Result = r, Order = o }) 
    .OrderBy(o => o.Order) 
    .Select(o => o.Result); 

Позвони по телефону ToArray() в случайных числах, это не изменится. Когда вы, наконец, захотите предметов в result, вы можете закрепить предметы со случайными номерами, OrderBy случайным числом и Select результатом.

Если у вас есть вопросы в result, в таком же порядке, результат в orderedResult должен быть одинаковым.

+0

Это решение по-прежнему удваивает исходный размер результата. Понятно, что это примерно эквивалентно материализации «IEnumerable». – Marc

+0

Как это? если каждый элемент 'result1' - это класс, который содержит много полей, это много данных. Это будет только удвоение, если каждый элемент 'result1' содержит одно поле размером int. Решение, которое я здесь привел, будет потреблять память, хранящую случайные числа, но на самом деле получение данных результата отложено. – Lukazoid

+0

Кто сказал, что это объекты? На OP они кажутся целыми числами. – Marc

5

Вы ищете алгоритм шаффле .

См следующие SO темы, чтобы обеспечить только вежливые расширения методов, чтобы сделать работу:

Is using Random and OrderBy a good shuffle algorithm?

An extension method on IEnumerable needed for shuffling


Для того, чтобы ответить на ваш вопрос "? Почему это перемешиваются снова", это потому, что о том, как работает OrderBy (ленивое исполнение). Вы можете попробовать:

var result2 = result1.OrderBy(order=>random.Next()).ToList(); 
+0

Я проигнорировал, потому что реализация его перетасовки не находится в центре вопроса – soniiic

+0

@soniiic, пожалуйста, см. Обновленный ответ – ken2k

1

Вы можете использовать ToList() так:

var result2 = result1.OrderBy(order=>random.Next()).ToList(); 
+1

Агенту требуется ленивая/отсроченная оценка, поскольку элементы 'result1' имеют большой размер. – Lukazoid

+0

Но в какой-то момент он должен быть перечислим, поэтому ассер должен «ToList()» как можно позже, а затем вывести результирующий набор на все, что ему нужно. – soniiic

+0

Что делать, если у искателя была какая-то форма разбивки на страницы? т. е. «Пропустить (20) .Выберите (10)», тогда количество данных на машине-клиенте будет меньше, но если «OrderBy» оценивается перед каждым вызовом с разбивкой по страницам, заказы будут отличаться по-разному. – Lukazoid

Смежные вопросы