我已经从枚举中选择了随机值,如下所示:
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))];
}
答案 0 :(得分: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 :正如Idan Arye所指出的,模板可能更为简洁:
T RandomEnumElement(T)() if (is(T == enum)){
return [EnumMembers!T][(uniform(0, $))];
}
编辑3 : tgehr 提出了以下解决方案,它将在编译时构建一次查找表并完全避免GC分配:
T RandomEnumElement(T)() if (is(T == enum)) {
static immutable members = [EnumMembers!T];
return members[uniform(0, $)];
}