2011-08-31 36 views
12

Trong Python, tôi có thể làm điều này:C#: Mã Elegant để có được một giá trị ngẫu nhiên từ một IEnumerable

>>> import random 
>>> ints = [1,2,3] 
>>> random.choice(ints) 
3 

Trong C#, điều đầu tiên tôi làm là:

var randgen = new Random(); 
var ints = new int[] { 1, 2, 3 }; 
ints[randgen.Next(ints.Length)]; 

Nhưng điều này đòi hỏi lập chỉ mục , cũng là sự trùng lặp của ints làm phiền tôi. Vì vậy, tôi đã đưa ra điều này:

var randgen = new Random(); 
var ints = new int[] { 1, 2, 3 }; 
ints.OrderBy(x=> randgen.Next()).First(); 

Vẫn không đẹp và hiệu quả. Có cách nào thanh lịch hơn để nhận giá trị ngẫu nhiên từ IEnumberable không?

+2

Giả sử bạn có nghĩa là 'IEnumerable', nhưng với câu hỏi tôi có một LOL trong số' IEnumberable' :) – Yuck

+0

Nguồn gốc của 'IEnumerable' là gì? – Gabe

+0

Chức năng RandomElement dường như là những gì bạn đang tìm kiếm. http://stackoverflow.com/questions/648196/random-row-from-linq-to-sql/648240#648240 –

Trả lời

3

Không, đó là cách đơn giản nhất. Tất nhiên, đó chỉ là bán ngẫu nhiên, nhưng tôi nghĩ nó phù hợp với hầu hết nhu cầu.

EDIT: lớn Point đây ...

Nếu bạn chỉ muốn ONE giá trị được chọn ngẫu nhiên từ danh sách ... sau đó chỉ cần làm điều này:

var myRandomValue = ints[(new Random()).Next(0, ints.Length)]; 

Đó là một O (1) hoạt động.

+0

Ý bạn là "bán ngẫu nhiên" là gì? – NullUserException

+2

Lớp ngẫu nhiên tạo ra các số giả ngẫu nhiên, chứ không phải số ngẫu nhiên mã hóa mạnh. –

+1

@Chris Tôi biết giả ngẫu nhiên là gì. Tôi không biết "bán ngẫu nhiên" nghĩa là gì. Và giả ngẫu nhiên không loại trừ nó khỏi an toàn mã hóa, ví dụ: 'mạnh mã hóa! = (! Giả ngẫu nhiên)' – NullUserException

3

Sắp xếp sẽ kém hiệu quả hơn nhiều. Chỉ cần sử dụng Skip (n) và First():.

var randgen = new Random(); 
var ints = new int[] { 1, 2, 3}; 

ints.Skip (x => randgen.Next (0, ints.Count())) Đầu tiên();

ints.ElementAt(x=> randgen.Next(0, ints.Count())); 
+0

Paren cuối cùng được cho là trước '.irst()'? – ANeves

+0

Có lỗi. Đã sửa. –

+1

Tại sao nên sử dụng '.Skip (N) .First()' thay vì '.ElementAt (N)'? – Gabe

1

Làm thế nào về một cái gì đó đơn giản và dễ đọc:

ints[randgen.Next(ints.Length)]; 

Nghiêm túc, tại sao xáo trộn mã của bạn với lambdas .OrderBy và .First và .Skip và vân vân !?

+3

[] sẽ không hoạt động với IEnumerable, đó là những gì mà người đăng ký yêu cầu. Tôi không nghĩ rằng các poster muốn một mảng hoặc giải pháp dựa trên danh sách, mà như bạn chỉ ra, là đơn giản. –

+0

Ah, điểm tốt. cảm ơn. – fredw

16

Dưới đây là một phương pháp vài phần mở rộng dành cho bạn:

public static T RandomElement<T>(this IEnumerable<T> enumerable) 
{ 
    return enumerable.RandomElementUsing<T>(new Random()); 
} 

public static T RandomElementUsing<T>(this IEnumerable<T> enumerable, Random rand) 
{ 
    int index = rand.Next(0, enumerable.Count()); 
    return enumerable.ElementAt(index); 
} 

// Usage: 
var ints = new int[] { 1, 2, 3 }; 
int randomInt = ints.RandomElement(); 

// If you have a preexisting `Random` instance, rand, use it: 
// this is important e.g. if you are in a loop, because otherwise you will create new 
// `Random` instances every time around, with nearly the same seed every time. 
int anotherRandomInt = ints.RandomElementUsing(rand); 

Đối với một vị tướng IEnumerable<T>, đây sẽ là O (n ), vì đó là sự phức tạp của .Count() và ngẫu nhiên .ElementAt() cuộc gọi; tuy nhiên, cả hai trường hợp đặc biệt cho mảng và danh sách, vì vậy trong những trường hợp đó, nó sẽ là O (1).

+1

Tuy nhiên, lưu ý rằng nó thực hiện hai lần truyền dữ liệu, điều này có thể gây ra vấn đề nếu tập dữ liệu thay đổi giữa cuộc gọi đến 'Đếm' và cuộc gọi đến' ElementAt'. (Không phải là một vấn đề ở đây, nhưng có thể là một vấn đề nói chung.) –

+4

Đúng; Câu trả lời của Jon Skeet tại http://stackoverflow.com/questions/648196/random-row-from-linq-to-sql/648240#648240 có lẽ là câu trả lời hay nhất về vấn đề đó. – Domenic

+1

nó sẽ không là một vấn đề nếu nó tìm kiếm một ElementAt (enum.Count())? Giả sử một enum có 5 mục, và rand chọn 5. Enum.ElementAt (5) sẽ không tìm thấy gì cả, đúng không? – AnimaSola

Các vấn đề liên quan