2012-08-27 22 views
8

tôi đã thực hiện để chọn các giá trị ngẫu nhiên từ sự đếm như vậy:Chọn một yếu tố ngẫu nhiên của một enum trong D

import std.random : uniform; 
import std.stdio : writefln; 
import std.conv; 

enum E {A, B, C} 

int main(){ 
    auto select = cast(E)uniform(to!int(E.min), to!int(E.max)); 
    writefln("select %s", select); 
    return 0; 
} 

này bất ngờ tiết, và dễ bị các vấn đề nếu có thành viên enum có giá trị bên ngoài mặc định (hoặc lớn hơn int).

Lý tưởng nhất là tôi sẽ lấy một phạm vi đại diện cho các yếu tố của enum và cung cấp điều này cho randomSample. Tuy nhiên, điều này dường như không thể.

Có cách nào thành ngữ hơn để chọn một giá trị ngẫu nhiên từ một enum trong D không?

EDIT:

Sử dụng câu trả lời cung cấp bởi fwend, đây là một hàm mẫu đạt được những gì tôi muốn:

T RandomEnumElement(T)() if (is(T == enum)){ 
    auto members = [EnumMembers!T]; 
    return members[(uniform(0, members.length))]; 
} 

Trả lời

9
import std.random : uniform; 
import std.stdio : writefln; 
import std.conv; 
import std.traits; 

enum E {A, B, C} 

int main(){ 
    auto select = [EnumMembers!E][uniform(0, 3)]; 
    writefln("select %s", select); 
    return 0; 
} 

Sửa: nếu bạn cần phải sử dụng enum giá trị nhiều hơn một lần, bạn có thể lưu trữ chúng trong một mảng bất biến tĩnh đầu tiên, nếu không mảng sẽ được xây dựng mỗi lần. Đó cũng cho phép bạn để có được thoát khỏi những con số kỳ diệu 3.

(...) 
int main(){ 
    static immutable Evalues = [EnumMembers!E]; 
    auto select1 = Evalues[uniform(0, Evalues.length)]; 
    writefln("select %s", select1); 

    auto select2 = Evalues[uniform(0, Evalues.length)]; 
    writefln("select %s", select2); 
    return 0; 
} 

Chỉnh sửa 2: Như đã chỉ ra bởi Idan Arye, mẫu có thể còn terser:

T RandomEnumElement(T)() if (is(T == enum)){ 
    return [EnumMembers!T][(uniform(0, $))]; 
} 

Chỉnh sửa 3: tgehr đã đề xuất giải pháp sau, sẽ xây dựng bảng tra cứu một lần tại thời gian biên dịch và tránh phân bổ GC hoàn toàn:

T RandomEnumElement(T)() if (is(T == enum)) { 
    static immutable members = [EnumMembers!T]; 
    return members[uniform(0, $)]; 
} 
+0

Hiện tại bản chỉnh sửa không biên dịch, 'Đánh giá' cần loại' E [] '. – cmh

+0

@cmh Lạ, nó biên soạn tốt với tôi. dmd 2.060 win7 – fwend

+0

Xin lỗi nó hoạt động, nó cần đối số khi bên trong một hàm mẫu. – cmh

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