सूची में यादृच्छिक आइटम का उपयोग कैसे करें?


233

मेरे पास एक ArrayList है, और मुझे एक बटन क्लिक करने में सक्षम होने की आवश्यकता है और फिर उस सूची से एक स्ट्रिंग को बेतरतीब ढंग से बाहर निकालने और इसे एक संदेश बॉक्स में प्रदर्शित करने की आवश्यकता है।

मैं ऐसा कैसे कर पाऊंगा?

जवाबों:


404
  1. Randomकहीं कक्षा का उदाहरण बनाएँ । ध्यान दें कि हर बार आपको एक यादृच्छिक संख्या की आवश्यकता होने पर एक नया उदाहरण नहीं बनाना बहुत महत्वपूर्ण है। आपको जनरेट की गई संख्या में एकरूपता प्राप्त करने के लिए पुराने उदाहरण का पुनः उपयोग करना चाहिए। आपके पास एक staticक्षेत्र हो सकता है (थ्रेड सुरक्षा मुद्दों के बारे में सावधान रहें):

    static Random rnd = new Random();
  2. Randomउदाहरणों से पूछें कि आपको मदों की अधिकतम संख्या के साथ एक यादृच्छिक संख्या देने के लिए ArrayList:

    int r = rnd.Next(list.Count);
  3. स्ट्रिंग प्रदर्शित करें:

    MessageBox.Show((string)list[r]);

क्या इसे संशोधित करने का कोई अच्छा तरीका है ताकि कोई संख्या दोहराई न जाए? मान लीजिए कि मैं एक समय में एक का चयन करके कार्ड के डेक को फेरबदल करना चाहता था, लेकिन स्पष्ट रूप से एक ही कार्ड का दो बार चयन नहीं कर सकता।
एडमएमसी 331

7
@ McAdam331 देखो ऊपर फिशर-येट्स घसीटना एल्गोरिथ्म: en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Mehrdad Afshari

2
एलीमेंट तत्व अधिकतम तक पहुँचने से बचने के लिए क्या यह "rnd.Next (list.Count-1)" के बजाय "rnd.Next (list.Count)" होना चाहिए, जो कि संभवतः 0-आधारित इंडेक्स से परे होगा?
बी क्ले शैनन

22
@ B.ClayShannon No. Next(max)कॉल में ऊपरी स्थान अनन्य है।
मेहरदाद अफश्री

1
सूची खाली होने पर क्या होगा?
tsu1980

137

मैं आमतौर पर विस्तार विधियों के इस छोटे संग्रह का उपयोग करता हूं:

public static class EnumerableExtension
{
    public static T PickRandom<T>(this IEnumerable<T> source)
    {
        return source.PickRandom(1).Single();
    }

    public static IEnumerable<T> PickRandom<T>(this IEnumerable<T> source, int count)
    {
        return source.Shuffle().Take(count);
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
    {
        return source.OrderBy(x => Guid.NewGuid());
    }
}

जोरदार टाइप की गई सूची के लिए, यह आपको लिखने की अनुमति देगा:

var strings = new List<string>();
var randomString = strings.PickRandom();

यदि आपके पास एक ArrayList है, तो आप इसे डाल सकते हैं:

var strings = myArrayList.Cast<string>();

उन की जटिलता क्या है? क्या IEnumerable की आलसी प्रकृति का मतलब यह है कि यह O (N) नहीं है?
डेव हिलियर

17
हर बार जब आप एक यादृच्छिक संख्या चुनते हैं तो यह उत्तर सूची को फिर से फेरबदल करता है। यह विशेष रूप से बड़ी सूचियों के लिए एक यादृच्छिक सूचकांक मूल्य को वापस करने के लिए बहुत अधिक कुशल होगा। इस का उपयोग पिकड्रैगन में - return list[rnd.Next(list.Count)];
३-२४ बजे

यह मूल सूची में फेरबदल नहीं करता है, यह वास्तव में एक और सूची पर है जो अभी भी दक्षता के लिए अच्छा नहीं हो सकता है यदि सूची काफी बड़ी है ..
nawfal

.OrderBy (।) एक और सूची नहीं बनाता है - यह एक प्रकार की वस्तु बनाता है IEnumerable <T> जो मूल सूची के माध्यम से एक क्रमबद्ध तरीके से पुनरावृत्ति कर रहा है।
जोहान टिडेन

5
GUID पीढ़ी एल्गोरिथ्म अप्रत्याशित है, लेकिन यादृच्छिक नहीं है। Randomइसके बजाय स्थिर अवस्था में एक उदाहरण रखने पर विचार करें ।
दाई

90

तुम कर सकते हो:

list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()

सुंदर। ASP.NET MVC 4.5 में, एक सूची का उपयोग करें, मुझे इसे बदलना था: list.OrderBy (x => Guid.NewGuid ())। FirstOrDefault ();
एंडी ब्राउन

3
यह ज्यादातर मामलों में मायने नहीं रखेगा, लेकिन यह शायद rnd.Next का उपयोग करने की तुलना में बहुत धीमा है। OTOH यह IEnumerable <T> पर काम करेगा, न कि केवल सूचियों पर।
२०:२४

12
निश्चित नहीं है कि यह कितना यादृच्छिक है। गाइड अद्वितीय हैं, यादृच्छिक नहीं।
पोम्बर

1
मुझे लगता है कि इस उत्तर का एक बेहतर और विस्तारित संस्करण और @ घुलनशील मछली की टिप्पणी अच्छी तरह से इस जवाब में जोड़ दी गई है (साथ ही मेरी टिप्पणी ) एक समान प्रश्न के लिए।
नियो

23

एक Randomउदाहरण बनाएँ :

Random rnd = new Random();

एक यादृच्छिक स्ट्रिंग प्राप्त करें:

string s = arraylist[rnd.Next(arraylist.Count)];

हालाँकि, याद रखें कि यदि आप ऐसा बार-बार करते हैं, तो आपको Randomऑब्जेक्ट का पुनः उपयोग करना चाहिए । इसे कक्षा में एक स्थिर क्षेत्र के रूप में रखें ताकि यह केवल एक बार इनिशियलाइज़ हो और फिर इसे एक्सेस करें।


20

या इस तरह सरल विस्तार वर्ग:

public static class CollectionExtension
{
    private static Random rng = new Random();

    public static T RandomElement<T>(this IList<T> list)
    {
        return list[rng.Next(list.Count)];
    }

    public static T RandomElement<T>(this T[] array)
    {
        return array[rng.Next(array.Length)];
    }
}

तो बस कॉल करें:

myList.RandomElement();

सरणियों के लिए भी काम करता है।

मैं कॉल करने से बचूंगा OrderBy()क्योंकि यह बड़े संग्रह के लिए महंगा हो सकता है। List<T>इस उद्देश्य के लिए अनुक्रमित संग्रह जैसे या सरणियों का उपयोग करें ।


3
.NET में एरर्स पहले से ही लागू है IListइसलिए दूसरा ओवरलोड अनावश्यक है।
दाईं

3

क्यों नहीं:

public static T GetRandom<T>(this IEnumerable<T> list)
{
   return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}

2
ArrayList ar = new ArrayList();
        ar.Add(1);
        ar.Add(5);
        ar.Add(25);
        ar.Add(37);
        ar.Add(6);
        ar.Add(11);
        ar.Add(35);
        Random r = new Random();
        int index = r.Next(0,ar.Count-1);
        MessageBox.Show(ar[index].ToString());

3
हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और उन लोगों को आपके कोड सुझाव के कारणों का पता नहीं चल सकता है।
gunr2171

3
मैं कहूंगा, कि maxValueविधि का पैरामीटर Nextसूची में केवल तत्वों का एक नंबर होना चाहिए, ना कि माइनस एक, क्योंकि एक प्रलेखन के अनुसार " maxValue यादृच्छिक संख्या का अनन्य ऊपरी भाग है "।
डेविड फेरेंस्की रोगोजान

1

मैं थोड़ी देर के लिए इस ExtensionMethod का उपयोग कर रहा हूँ:

public static IEnumerable<T> GetRandom<T>(this IEnumerable<T> list, int count)
{
    if (count <= 0)
      yield break;
    var r = new Random();
    int limit = (count * 10);
    foreach (var item in list.OrderBy(x => r.Next(0, limit)).Take(count))
      yield return item;
}


1

मैं अलग दृष्टिकोण का सुझाव दूंगा, यदि सूची के अंदर वस्तुओं का क्रम निष्कर्षण पर महत्वपूर्ण नहीं है (और प्रत्येक आइटम को केवल एक बार चुना जाना चाहिए), तो इसके बजाय Listआप एक का उपयोग कर सकते हैं ConcurrentBagजो एक थ्रेड-सुरक्षित, अनियोजित संग्रह है वस्तुओं:

var bag = new ConcurrentBag<string>();
bag.Add("Foo");
bag.Add("Boo");
bag.Add("Zoo");

द इवेंटहैंडलर:

string result;
if (bag.TryTake(out result))
{
    MessageBox.Show(result);
}

TryTakeअव्यवस्थित संग्रह से एक "यादृच्छिक" वस्तु को निकालने के लिए प्रयास करेंगे।


0

मुझे सिर्फ एक के बजाय अधिक आइटम की आवश्यकता थी। तो, मैंने यह लिखा:

public static TList GetSelectedRandom<TList>(this TList list, int count)
       where TList : IList, new()
{
    var r = new Random();
    var rList = new TList();
    while (count > 0 && list.Count > 0)
    {
        var n = r.Next(0, list.Count);
        var e = list[n];
        rList.Add(e);
        list.RemoveAt(n);
        count--;
    }

    return rList;
}

इसके साथ, आप ऐसे तत्व प्राप्त कर सकते हैं जिन्हें आप यादृच्छिक रूप से इस तरह चाहते हैं:

var _allItems = new List<TModel>()
{
    // ...
    // ...
    // ...
}

var randomItemList = _allItems.GetSelectedRandom(10); 

0

JSON फ़ाइल से यादृच्छिक रूप से देश का नाम प्रिंट करना।
नमूना:

public class Country
    {
        public string Name { get; set; }
        public string Code { get; set; }
    }

Implementaton:

string filePath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\..\..\")) + @"Data\Country.json";
            string _countryJson = File.ReadAllText(filePath);
            var _country = JsonConvert.DeserializeObject<List<Country>>(_countryJson);


            int index = random.Next(_country.Count);
            Console.WriteLine(_country[index].Name);

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.