डी

2012-08-27 10 views
8

में एक enum के एक यादृच्छिक तत्व का चयन करें मैं इतनी तरह enums से यादृच्छिक मान का चयन करने ले लिया है:डी

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

यह आश्चर्यजनक रूप से अत्यधिक शब्द, और मुद्दों की संभावना है, यदि कोई हो enum सदस्यों डिफ़ॉल्ट बाहर के मान लेना (या int से बड़ा)।

आदर्श रूप से मैं एक सीमा लेता हूं जो enum के तत्वों का प्रतिनिधित्व करता है, और इसे randomSample पर प्रदान करता है। हालांकि, यह संभव नहीं प्रतीत होता है।

क्या डी में एनम से यादृच्छिक मूल्य चुनने का एक और बेवकूफ तरीका है?

संपादित करें:

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

संपादित: आप का उपयोग करने की आवश्यकता है enum मान एक से अधिक बार, आप उन्हें पहले एक स्थिर अपरिवर्तनीय सरणी में स्टोर कर सकते हैं, अन्यथा सरणी हर बार बनाया जाएगा। यही कारण है कि यह भी आप जादुई संख्या 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 से कहा, टेम्पलेट भी terser हो सकता है:

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

संपादित करें 3: tgehr ने निम्न समाधान का सुझाव दिया है, जो संकलन समय पर एक बार लुकअप टेबल का निर्माण करेगा और जीसी आवंटन से पूरी तरह से बच जाएगा:

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

वर्तमान में संपादन संकलित नहीं होता है, 'Evalues' की आवश्यकता है' ई [] '। – cmh

+0

@cmh अजीब, यह मेरे साथ बस ठीक है। डीएमडी 2.060 win7 – fwend

+0

क्षमा करें यह काम करता है, टेम्पलेट फ़ंक्शन के अंदर तर्क की आवश्यकता होती है। – cmh