在d

2012-08-27 24 views
8

選擇一個枚舉的隨機元素我已經採取措施來從枚舉選擇隨機值,如下所示:在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; 
} 

這是令人驚訝的冗長,且易發生問題,如果任何枚舉成員採取默認以外的值(或大於int)。

理想情況下,我將採用代表枚舉元素的範圍,並將其提供給randomSample。但是,這似乎不可能。

是否有一種更習慣的方式來從D中的枚舉中選擇一個隨機值?

編輯:

使用fwend提供的答案,這裏是一個模板函數的實現我想要什麼:

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

回答

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; 
} 

編輯:如果你需要使用枚舉值不止一次,你可以先將它們存儲在一個靜態不可變數組中,否則每次都會建立數組。這也可以讓你擺脫幻數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; 
} 

編輯2的:由於伊詹阿里耶指出,模板可能甚至更簡潔:

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

編輯3tgehr已經提出了以下解決方案,它將在編譯時構建查找表一次,並完全避免GC分配:

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

目前編輯不編譯,'Evalues'需要輸入'E []'。 – cmh

+0

@cmh奇怪,它編譯得很好。 dmd 2.060 win7 – fwend

+0

道歉,它確實工作,它需要在模板函數內的參數。 – cmh

相關問題