Я хочу сгенерировать массив, который имеет 144 числа из 1-> 36 в случайном порядке (поэтому каждое число повторяется 4 раза). Можем ли мы использовать Enumerable.Repeat и Enumerable.Range для этого. Если да, то пожалуйста объясните мне как?Сгенерировать и повторить число в C#
ответ
Ну, создавая последовательность со всеми числами в легко:
var items = from x in Enumerable.Range(1, 36)
from y in Enumerable.Repeat(x, 4)
select y;
Тогда вы можете просто использовать ToArray
, чтобы получить его в массив и перемешайте его. Существует множество вопросов о перетасовке массива в C# на SO, например this one. Вы можете использовать этот код напрямую или позвонить ToArray
и перетасовать массив на месте, не уступая его в конце.
int[] numbers = Enumerable.Range(0, 144).Select(i => (i % 36)+1).OrderBy(g => Guid.NewGuid()).ToArray();
Возможно, это не важно в этом случае, но этот способ перетасовки заканчивается тем, что O (n log n), где ему только нужно быть O (п). –
// Generate the list (not in random order)
var one_to_36 = Enumerable.Range(1, 36);
var lst = one_to_36.Concat(one_to_36).Concat(one_to_36).Concat(one_to_36).ToList();
// Randomize the list by swapping random elements
Random rnd = new Random();
for(int i = 0; i < lst.Count; i++)
{
int i1 = rnd.Next(lst.Count);
int i2 = rnd.Next(lst.Count);
int tmp = lst[i1];
lst[i1] = lst[i2];
lst[i2] = tmp;
}
Обмен случайными элементами таким образом не дает хорошего случайного распределения - есть лучший способ перетасовки коллекции, как это связано с моим ответом. –
Я не понимал, что ... спасибо за подсказку –
var seq = Enumerable.Range(0, 144);
var all = seq.ToList();
var random = new Random();
var result = seq.Select(i => {
var index = random.Next()%all.Count;
var r = all[index] % 36 + 1; all.RemoveAt(index);
return r;
}).ToList();
эй, это более читаемым, чем мое решение. +1 –
и более элегантный, что мой многократный Concat;) –
спасибо за комментарий, но теперь мне нужно заполнить сгенерированный массив массивом [9,16], можете ли вы предложить хороший способ для меня? –