একটি তালিকা এলোমেলো করে <T>


852

সি # তে জেনেরিক তালিকার ক্রমটি এলোমেলো করার সর্বোত্তম উপায় কী? লটারির ধরণের অ্যাপ্লিকেশনটি আঁকার জন্য আমি একটি তালিকার 75 টি সংখ্যার একটি সীমাবদ্ধ সেট পেয়েছি to


3
এই কার্যকারিতাটি। নেট: github.com/dotnet/corefx/issues/461
নাটান

5
আপনি এই নুগেট প্যাকেজটিতে আগ্রহী হতে পারেন , যার মধ্যে নীচে উল্লিখিত ফিশার-ইয়েটস অ্যালগোরিদম ব্যবহার করে আইএললিস্ট <T> এবং আইনিউবারেবল <T> পরিবর্তনের জন্য এক্সটেনশন পদ্ধতি রয়েছে
চেজমেডালিয়ন

3
@ নাটান তারা বিষয়টি বন্ধ করেছেন কারণ কেউ "অনেক প্রকল্পে কাজ করেছেন এবং অনেক লাইব্রেরি তৈরি করেছেন এবং কখনও এ জাতীয় পদ্ধতির প্রয়োজন হয়নি" যা আমাকে হতাশ করেছিল। এখন আমাদের নিজের তদন্ত করতে হবে, সর্বোত্তম বাস্তবায়নগুলি অনুসন্ধান করতে হবে, চাকাটি পুনরায় উদ্ভাবনের জন্য সময় নষ্ট করতে হবে।
ভিটালি আইসেনকো

1
আমি কি এই অধিকার দেখতে পাচ্ছি? 10 বছর পরে একটি বৈধ কার্যকরী উত্তর না? Numbers৫ নম্বর $ লগ ​​২ (!)!) = ৩$৪ this এবং আমরা কীভাবে এটি পেতে পারি তা দিয়ে একটি তালিকা পরিবর্তন করতে পারে এমন একটি সমাধানের জন্য আমাদের আরেকটি অনুগ্রহের প্রয়োজন হতে পারে যা প্রয়োজনীয় এনট্রপির পরিমাণের সাথে সম্পর্কিত হয়। একজনকে ফিশার ইয়েটস বদলের সময় কমপক্ষে একবার 256 বিট এনট্রপির সাথে একটি ক্রিপ্টোগ্রাফিক সুরক্ষিত আরএনজি পুনরায় গবেষণা করতে হবে।
ফালকো

1
এবং যদি সাধারণ কোডার এই সমস্যাটি সমাধান করতে না পারে তবে আমরা কি চিরকালের জন্য সম্ভব সলিটায়ার গেমগুলির একই 0.01% খেলছি?
ফালকো

উত্তর:


1135

ফিশার-ইয়েটস শাফলের(I)List উপর ভিত্তি করে কোনও এক্সটেনশন পদ্ধতির সাথে যেকোনও শাফল করুন :

private static Random rng = new Random();  

public static void Shuffle<T>(this IList<T> list)  
{  
    int n = list.Count;  
    while (n > 1) {  
        n--;  
        int k = rng.Next(n + 1);  
        T value = list[k];  
        list[k] = list[n];  
        list[n] = value;  
    }  
}

ব্যবহার:

List<Product> products = GetProducts();
products.Shuffle();

উপরের কোডটিতে অদলবদ প্রার্থীদের বাছাই করতে অনেক সমালোচিত সিস্টেম.র্যান্ডম পদ্ধতি ব্যবহার করা হয়েছে। এটি দ্রুত তবে এটির মতো এলোমেলো নয়। আপনার শ্যাফলে যদি আপনার আরও ভাল মানের র্যান্ডমনেস প্রয়োজন হয় তবে সিস্টেমে র্যান্ডম নম্বর জেনারেটরটি ব্যবহার করুন ec

using System.Security.Cryptography;
...
public static void Shuffle<T>(this IList<T> list)
{
    RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
    int n = list.Count;
    while (n > 1)
    {
        byte[] box = new byte[1];
        do provider.GetBytes(box);
        while (!(box[0] < n * (Byte.MaxValue / n)));
        int k = (box[0] % n);
        n--;
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}

একটি সহজ তুলনা এই ব্লগে উপলব্ধ (ওয়েব্যাক মেশিন)।

সম্পাদনা: কয়েক বছর আগে এই উত্তরটি লেখার পরে, আমার তুলনায় বড় বোকা ত্রুটি চিহ্নিত করার জন্য অনেকেই আমাকে মন্তব্য করেছেন বা লিখেছেন। তারা অবশ্যই সঠিক। সিস্টেমের সাথে কোনও ভুল নেই and র্যান্ডম যদি এটির মতোভাবে ব্যবহার করা হয়। উপরের আমার প্রথম উদাহরণে, আমি শাফল পদ্ধতির অভ্যন্তরে আরএনজি ভেরিয়েবলটি ইনস্ট্যান্ট করি, যা পদ্ধতিটি বারবার বলা হচ্ছে কিনা তার জন্য সমস্যা জিজ্ঞাসা করছে। নীচে এখানে একটি ওয়েস্টন থেকে এসওতে প্রাপ্ত সত্যিকারের দরকারী মন্তব্যের ভিত্তিতে একটি স্থির, পূর্ণ উদাহরণ example

Program.cs:

using System;
using System.Collections.Generic;
using System.Threading;

namespace SimpleLottery
{
  class Program
  {
    private static void Main(string[] args)
    {
      var numbers = new List<int>(Enumerable.Range(1, 75));
      numbers.Shuffle();
      Console.WriteLine("The winning numbers are: {0}", string.Join(",  ", numbers.GetRange(0, 5)));
    }
  }

  public static class ThreadSafeRandom
  {
      [ThreadStatic] private static Random Local;

      public static Random ThisThreadsRandom
      {
          get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
      }
  }

  static class MyExtensions
  {
    public static void Shuffle<T>(this IList<T> list)
    {
      int n = list.Count;
      while (n > 1)
      {
        n--;
        int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
      }
    }
  }
}

31
যদি তালিকা.কাউন্ট হয়> বাইট.ম্যাক্সভ্যালু? যদি এন = 1000 হয়, তবে 255/1000 = 0, তাই ডু লুপটি একটি অসীম লুপ হবে কারণ বাক্স [0] <0 সর্বদা মিথ্যা।
অ্যান্ড্রুস

18
আমি উল্লেখ করতে চাই, যে তুলনা ত্রুটিযুক্ত। ব্যবহার <কোড> নতুন এলোমেলো () </ code> এ একটি লুপ সমস্যা, না <কোড> এলোমেলো </ code> এ এর যদৃচ্ছতা হয় ব্যাখ্যা
সেভেন

9
এলোমেলোভাবে উদাহরণটি এলোমেলোভাবে পরিবর্তনের পরিবর্তে এলোমেলো করে দেওয়া ভাল ধারণা যে আপনি দ্রুত উত্তরাধিকারসূত্রে প্রচুর বার শাফলকে ডাকছেন (যেমন সংক্ষিপ্ত তালিকাগুলিতে প্রচুর পরিমাণে পরিবর্তন করা), তালিকাগুলি একই রকম হয়ে যাবে উপায় (যেমন প্রথম আইটেম সর্বদা 3 অবস্থানে স্থানান্তরিত হয়)।
মার্ক হিথ

7
তুলনা পোস্টে কেবল Random rng = new Random();একটি তৈরি করা staticসমস্যার সমাধান করবে। প্রতিটি পরবর্তী কলটি পূর্ববর্তী কলগুলি থেকে শেষ র্যান্ডম ফলাফল অনুসরণ করবে।
ওয়েস্টন

5
# 2, এটি স্পষ্ট নয় যে ক্রিপ্টো জেনারেটরের সাথে সংস্করণটি কাজ করে কারণ একটি বাইটের সর্বাধিক পরিসীমা 255, সুতরাং এর চেয়ে বড় কোনও তালিকা সঠিকভাবে বদলে যাবে না।
মার্ক সোওল

336

আমাদের যদি কেবলমাত্র সম্পূর্ণ র্যান্ডম ক্রমে আইটেমগুলি স্থানান্তর করতে হয় (কেবলমাত্র তালিকার আইটেমগুলিকে মিশ্রিত করতে হয়) তবে আমি এই সাধারণ এখনও কার্যকর কোডটি পছন্দ করি যা গাইড দ্বারা আইটেমগুলি অর্ডার করে ...

var shuffledcards = cards.OrderBy(a => Guid.NewGuid()).ToList();

40
জিইউইডিগুলি বোঝানো হয় এলোমেলো নয় অনন্য। এর অংশটি মেশিন-ভিত্তিক এবং অন্য অংশ সময় ভিত্তিক এবং কেবল একটি ছোট অংশ এলোমেলো। blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx
Despertar

99
এটি একটি দুর্দান্ত মার্জিত সমাধান। আপনি যদি এলোমেলোতা তৈরির দিক নির্দেশনা ব্যতীত অন্য কিছু চান তবে কেবল অন্য কিছু দ্বারা অর্ডার করুন। উদাহরণস্বরূপ: var shuffledcards = cards.OrderBy(a => rng.Next()); compilr.com/grenade/sandbox/Program.cs
গ্রেনেড

20
অনুগ্রহ করে না. এটা ভুল. "এলোমেলোভাবে অর্ডার করা" পুরোপুরি কোনও বদল নয়: আপনি পক্ষপাতের পরিচয় দেন এবং আরও খারাপ, আপনি অসীম লুপগুলিতে যাওয়ার ঝুঁকি নিয়ে যান
ভিটো ডি তুলিও

77
@ ভিটোডিটুলিও: আপনি ভুল ধারণা পোষণ করছেন। আপনি যখন এলোমেলো তুলনা ফাংশন সরবরাহ করেন তখন আপনি অসীম লুপগুলি ঝুঁকিপূর্ণ করেন ; একটি সামঞ্জস্যপূর্ণ মোট ক্রম উত্পাদন করতে একটি তুলনা ফাংশন প্রয়োজন । একটি এলোমেলো চাবি ঠিক আছে। এই পরামর্শটি ভুল কারণ গাইডগুলি এলোমেলো হওয়ার গ্যারান্টিযুক্ত নয়, কারণ একটি এলোমেলো কী দ্বারা বাছাইয়ের কৌশলটি ভুল।
এরিক লিপার্ট

24
@ ডগ: NewGuidকেবলমাত্র এটি আপনাকে একটি অনন্য জিইউইডি দেয় বলে গ্যারান্টি দেয়। এটি এলোমেলোতা সম্পর্কে কোন গ্যারান্টি দেয়। যদি আপনি কোনও অনন্য মান তৈরি করা ব্যতীত অন্য কোনও উদ্দেশ্যে জিইউইডি ব্যবহার করেন তবে আপনি এটি ভুল করছেন।
এরিক লিপার্ট

120

আমি এখানে এই সাধারণ অ্যালগরিদমের সমস্ত আড়ম্বরপূর্ণ সংস্করণ দ্বারা কিছুটা অবাক হয়েছি। ফিশার-ইয়েটস (বা নুথ শফল) কিছুটা জটিল তবে খুব কমপ্যাক্ট। কেন এটা কৌতুকপূর্ণ? কারণ আপনার এলোমেলো নম্বর জেনারেটরটি r(a,b)যেখানে bঅন্তর্ভুক্তি বা একচেটিয়া রয়েছে তার মূল্য দেয় কিনা সেদিকে আপনার মনোযোগ দেওয়ার প্রয়োজন । আমি উইকিপিডিয়া বর্ণনাটিও সম্পাদনা করেছি যাতে লোকেরা সেখানে সিউডোকোডকে অন্ধভাবে অনুসরণ না করে এবং বাগগুলি সনাক্ত করতে শক্ত তৈরি না করে। নেট জন্য, পরবর্তী বিজ্ঞাপন ছাড়াই এর সাথে Random.Next(a,b)একচেটিয়া নম্বর প্রদান করে b, এটি কীভাবে সি # /। নেট এ প্রয়োগ করা যেতে পারে:

public static void Shuffle<T>(this IList<T> list, Random rnd)
{
    for(var i=list.Count; i > 0; i--)
        list.Swap(0, rnd.Next(0, i));
}

public static void Swap<T>(this IList<T> list, int i, int j)
{
    var temp = list[i];
    list[i] = list[j];
    list[j] = temp;
}

এই কোড ব্যবহার করে দেখুন


Rnd (i, list.Count) কে rnd (0, list.Count) এ পরিবর্তন করা কি ভাল হবে না যাতে কোনও কার্ড অদলবদল হতে পারে?
ডোনটস

15
@ ডানটস - না যদি আপনি এটি করেন তবে আপনি এলোমেলোভাবে পক্ষপাতিত্ব যুক্ত করবেন।
শীতল শাহ

2
অদলবদল <T> কে আলাদা পদ্ধতিতে পৃথক করে দেখে মনে হচ্ছে আপনি টেম্পের জন্য প্রচুর অপ্রয়োজনীয় টি বরাদ্দ দিচ্ছেন।
ক্লে

2
আমি যুক্তি দিয়েছিলাম যে লিনকিউ সম্ভাব্যভাবে বদলানো কর্মক্ষমতা কমিয়ে দিতে পারে এবং বিশেষত কোডটির তুলনামূলক সরলতার কারণে এটি ব্যবহার না করার কারণ হবে।
উইংলারডব্লু

7
i = list.Count - 1সর্বশেষ পুনরাবৃত্তি কখন rnd.Next(i, list.Count)আপনাকে ফিরে দেবে give i < list.Count -1লুপ শর্ত হিসাবে আপনার প্রয়োজন । ঠিক আছে, আপনার এটির প্রয়োজন নেই, তবে এটি 1 পুনরাবৃত্তি সংরক্ষণ করে;)
পড

78

IEnumerable জন্য এক্সটেনশন পদ্ধতি:

public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
    Random rnd = new Random();
    return source.OrderBy<T, int>((item) => rnd.Next());
}

3
নোট করুন যে এটি থ্রেড-নিরাপদ নয়, এমনকি যদি থ্রেড-নিরাপদ তালিকায় ব্যবহার করা হয়
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

1
আমরা এই ফাংশনটিকে <স্ট্রিং> তালিকাটি কীভাবে দেব?
মনস্টার এমএমআরপিজি 7'13

8
এই অ্যালগরিদমের সাথে দুটি উল্লেখযোগ্য সমস্যা রয়েছে: - OrderByআইটেমগুলি তাদের (অবশ্যই এলোমেলো) কী দ্বারা বাছাই করতে একটি কুইকসোর্ট বৈকল্পিক ব্যবহার করে। কুইকসোর্ট কর্মক্ষমতা হ'ল ও (এন লগ এন) ; বিপরীতে, একটি ফিশার-ইয়েটস সাফেল হ'ল ও (এন) । 75 টি উপাদানের সংগ্রহের জন্য, এটি কোনও বড় বিষয় নাও হতে পারে তবে বৃহত্তর সংগ্রহের জন্য এই পার্থক্যটি উচ্চারণ করা হবে।
জন বেয়ার

10
... - Random.Next()মানগুলির যথাযথভাবে সিউডো-এলোমেলো বিতরণ তৈরি করতে পারে তবে মানগুলি অনন্য হবে তা গ্যারান্টি দেয় না । ডাব্লিকেট কীগুলির সম্ভাব্যতা এন -এর সাথে বৃদ্ধি পায় (অ-রৈখিকভাবে) যতক্ষণ না এটি নিশ্চিত হয়ে যায় যখন এন 2 ^ 32 + 1 এ পৌঁছায়। OrderByQuickSort একটি হল স্থিতিশীল সাজানোর; এইভাবে, একাধিক উপাদান একই সিউডো-রেণ্ডম সূচক মান নির্ধারিত করতে ঘটতে থাকে, তাহলে আউটপুট ক্রমানুসারে তাদের অর্ডার হতে হবে একই ইনপুট ক্রম হিসেবে; সুতরাং, "পক্ষান্তরে" একটি পক্ষপাতিত্ব চালু করা হয়।
জন বেয়ার

27
@ জনবায়ার: পক্ষপাতিত্বের উত্সের তুলনায় অনেক বেশি, অনেক বেশি সমস্যা রয়েছে। র‌্যান্ডমকে কেবলমাত্র চার বিলিয়ন সম্ভাব্য বীজ রয়েছে, এটি একটি মাঝারি আকারের সেটের সম্ভাব্য শ্যাফলের সংখ্যার চেয়ে অনেক কম। কেবলমাত্র সম্ভাব্য শ্যাফেলগুলির একটি ক্ষুদ্র ভগ্নাংশ তৈরি করা যেতে পারে। দুর্ঘটনাক্রমে সংঘর্ষের কারণে পক্ষপাতটি দ্বিখণ্ডিত হয়।
এরিক লিপার্ট

14

আইডিয়া আইটেম এবং এলোমেলো অর্ডার দিয়ে বেনামে বস্তু পেয়েছে এবং তারপরে এই অর্ডার এবং ফেরত মূল্য দ্বারা আইটেমগুলি পুনঃক্রম করুন:

var result = items.Select(x => new { value = x, order = rnd.Next() })
            .OrderBy(x => x.order).Select(x => x.value).ToList()

2
সেরা এক লাইনারের সমাধান
vipin8169

1
আপনি শেষ
ফাইতে

যদি কেউ আরএনডি সম্পর্কে অনিশ্চিত থাকে তবে এটিকে র্যান্ডম rnd = নতুন র‌্যান্ডম () এর উপরে কোডের পূর্বে যুক্ত করুন;
গ্রেগ ট্র্যাভেলিক

10
    public static List<T> Randomize<T>(List<T> list)
    {
        List<T> randomizedList = new List<T>();
        Random rnd = new Random();
        while (list.Count > 0)
        {
            int index = rnd.Next(0, list.Count); //pick a random item from the master list
            randomizedList.Add(list[index]); //place it at the end of the randomized list
            list.RemoveAt(index);
        }
        return randomizedList;
    }


4
var listCopy = list.ToList()আগত তালিকার সমস্ত আইটেম পপিং এড়ানোর মতো কিছু করা উচিত নয় ? আপনি কেন এই তালিকাটি খালি রূপান্তর করতে চান তা আমি সত্যিই দেখছি না।
ক্রিস মেরিসিক

9

সম্পাদনা দ্য RemoveAtআমার আগের সংস্করণে একটা দুর্বলতা। এই সমাধান যে কাটিয়ে উঠেছে।

public static IEnumerable<T> Shuffle<T>(
        this IEnumerable<T> source,
        Random generator = null)
{
    if (generator == null)
    {
        generator = new Random();
    }

    var elements = source.ToArray();
    for (var i = elements.Length - 1; i >= 0; i--)
    {
        var swapIndex = generator.Next(i + 1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
    }
}

Random generatorFrameworkচ্ছিক নোট করুন , যদি বেস কাঠামো বাস্তবায়নRandom থ্রেড-সেফ না হয় বা ক্রিপ্টোগ্রাফিকভাবে আপনার প্রয়োজনের জন্য যথেষ্ট শক্তিশালী না হয়, আপনি অপারেশনটিতে আপনার প্রয়োগকে ইনজেক্ট করতে পারেন।

থ্রেড-সেফ ক্রিপ্টোগ্রাফিকভাবে শক্তিশালী প্রয়োগের জন্য একটি উপযুক্ত প্রয়োগ Randomএই উত্তরে পাওয়া যাবে।


এখানে একটি ধারণা, একটি (আশাবাদী) দক্ষ উপায়ে IList প্রসারিত করুন।

public static IEnumerable<T> Shuffle<T>(this IList<T> list)
{
    var choices = Enumerable.Range(0, list.Count).ToList();
    var rng = new Random();
    for(int n = choices.Count; n > 1; n--)
    {
        int k = rng.Next(n);
        yield return list[choices[k]];
        choices.RemoveAt(k);
    }

    yield return list[choices[0]];
}


স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি / 4412405/ … দেখুন । আপনি অবশ্যই সচেতন হতে হবে।
নওফাল

@ নওফাল আমার উন্নত বাস্তবায়ন দেখুন।
জোডরেল

1
হুম যথেষ্ট ফর্সা। এটা GetNextনাকি Next?
নওফাল

4

এই সহজ এক্সটেনশন পদ্ধতিটি ব্যবহার করে আপনি তা অর্জন করতে পারেন

public static class IEnumerableExtensions
{

    public static IEnumerable<t> Randomize<t>(this IEnumerable<t> target)
    {
        Random r = new Random();

        return target.OrderBy(x=>(r.Next()));
    }        
}

এবং আপনি নিম্নলিখিতটি ব্যবহার করে এটি ব্যবহার করতে পারেন

// use this on any collection that implements IEnumerable!
// List, Array, HashSet, Collection, etc

List<string> myList = new List<string> { "hello", "random", "world", "foo", "bar", "bat", "baz" };

foreach (string s in myList.Randomize())
{
    Console.WriteLine(s);
}

3
আমি Randomক্লাস উদাহরণটি staticভেরিয়েবল হিসাবে ফাংশনের বাইরে রাখব । অন্যথায় আপনি যদি উত্তরাধিকার সূত্রে ডাকা হয় তবে আপনি টাইমার থেকে একই র্যান্ডমাইজেশন বীজ পেতে পারেন।
লেবুসীদ

একটি আকর্ষণীয় নোট - আপনি যদি এলোমেলো ক্লাসটি একটি লুপের মধ্যে দ্রুত ইনস্ট্যান্ট করেন, তবে প্রতিটি এমএসের 0 এমএস এবং 200 এমএসের মধ্যে বলুন, তবে আপনার একই র্যান্ডমাইজেশন বীজ পাওয়ার খুব বেশি সম্ভাবনা রয়েছে - যার ফলস্বরূপ পুনরাবৃত্তির ফলাফল হয়। তবে আপনি এলোমেলোভাবে এলোমেলো র্যান্ডম = নতুন র‌্যান্ডম (গাইড.নিউইউজিড ()। গেটহ্যাশকোড ()) ব্যবহার করে এটি পেতে পারেন; এটি কার্যকরভাবে গাইডটি নিউগুইড ()
বালেওস

4

আসলটি সংশোধন না করার পক্ষে যখন এটি পছন্দ হয় তখন এটাই আমার পছন্দসই পদ্ধতি। এটি ফিশার – ইয়েটসের "অভ্যন্তরীণ" অ্যালগরিদমের একটি বৈকল্পিক যা কোনও পরিমাণে অনুক্রমের উপর কাজ করে (দৈর্ঘ্যটি sourceশুরু থেকে জানা দরকার নেই)।

public static IList<T> NextList<T>(this Random r, IEnumerable<T> source)
{
  var list = new List<T>();
  foreach (var item in source)
  {
    var i = r.Next(list.Count + 1);
    if (i == list.Count)
    {
      list.Add(item);
    }
    else
    {
      var temp = list[i];
      list[i] = item;
      list.Add(temp);
    }
  }
  return list;
}

এই অ্যালগরিদম থেকে শুরু 0করে একটি ব্যাপ্তি বরাদ্দ করেও প্রয়োগ করা যেতে পারেlength - 1 এবং এলোমেলোভাবে গত সূচকের সাথে এলোমেলোভাবে নির্বাচিত সূচক সোয়াপিং পর্যন্ত সূচকের ঠিক একবার নির্বাচিত করা হয়েছে দ্বারা সূচকের ক্লান্তিকর। এই উপরের কোডটি ঠিক একই জিনিসটি সম্পাদন করে তবে অতিরিক্ত বরাদ্দ ছাড়াই। যা বেশ ঝরঝরে।

শুভেচ্ছার সঙ্গে Randomবর্গ এটি একটি সাধারণ কাজের সংখ্যা উত্পাদক (এবং যদি আমি একটি লটারি চলমান ছিল আমি ভিন্ন কিছু ব্যবহারের বিষয়ে বিবেচনা চাই)। এটি একটি সময় ভিত্তিক বীজ মান ডিফল্টর উপর নির্ভর করে। সমস্যার একটি ছোট বিমোচন হ'ল Randomশ্রেণীর বীজ বপন করা RNGCryptoServiceProviderবা আপনি RNGCryptoServiceProviderএটির অনুরূপ পদ্ধতিতে ব্যবহার করতে পারেন (নীচে দেখুন) অভিন্নভাবে বেছে নেওয়া এলোমেলো ডাবল ভাসমান পয়েন্টের মান উত্পন্ন করতে তবে লটারি চালানোর জন্য এলোমেলোতা এবং প্রকৃতির প্রকৃতি বোঝার প্রয়োজন এলোমেলো উত্স।

var bytes = new byte[8];
_secureRng.GetBytes(bytes);
var v = BitConverter.ToUInt64(bytes, 0);
return (double)v / ((double)ulong.MaxValue + 1);

একটি র্যান্ডম ডাবল উত্পন্ন করার বিন্দু (একচেটিয়াভাবে 0 এবং 1 এর মধ্যে) একটি পূর্ণসংখ্যার দ্রবণকে স্কেল করতে ব্যবহার করা। আপনার যদি xসর্বদা হতে চলেছে এমন এলোমেলো ডাবলের উপর ভিত্তি করে তালিকা থেকে কিছু বাছাই করা দরকার তবে 0 <= x && x < 1তা সরাসরি এগিয়ে।

return list[(int)(x * list.Count)];

উপভোগ করুন!


4

যদি আপনি দুটি ব্যবহার করতে আপত্তি করেন না Lists, তবে এটি সম্ভবত এটি করার সবচেয়ে সহজ উপায়, তবে সম্ভবত সবচেয়ে দক্ষ বা অবিশ্বাস্য উপায় নয়:

List<int> xList = new List<int>() { 1, 2, 3, 4, 5 };
List<int> deck = new List<int>();

foreach (int xInt in xList)
    deck.Insert(random.Next(0, deck.Count + 1), xInt);

3

আপনার যদি একটি নির্দিষ্ট নম্বর থাকে (75), আপনি 75 টি উপাদান দিয়ে একটি অ্যারে তৈরি করতে পারেন, তারপরে আপনার তালিকাটি গণনা করুন, উপাদানগুলিকে অ্যারেতে এলোমেলো অবস্থানে নিয়ে যাওয়া। আপনি ফিশার-ইয়েটস শ্যাফেল ব্যবহার করে অ্যারে সূচকে তালিকার সংখ্যার ম্যাপিং তৈরি করতে পারেন ।


3

আমি সাধারণত:

var list = new List<T> ();
fillList (list);
var randomizedList = new List<T> ();
var rnd = new Random ();
while (list.Count != 0)
{
    var index = rnd.Next (0, list.Count);
    randomizedList.Add (list [index]);
    list.RemoveAt (index);
}

list.RemoveAt একটি O (n) ক্রিয়াকলাপ, যা এই বাস্তবায়নটিকে বাধা দেয়।
জর্জ পোলেভয় 21

1
    List<T> OriginalList = new List<T>();
    List<T> TempList = new List<T>();
    Random random = new Random();
    int length = OriginalList.Count;
    int TempIndex = 0;

    while (length > 0) {
        TempIndex = random.Next(0, length);  // get random value between 0 and original length
        TempList.Add(OriginalList[TempIndex]); // add to temp list
        OriginalList.RemoveAt(TempIndex); // remove from original list
        length = OriginalList.Count;  // get new list <T> length.
    }

    OriginalList = new List<T>();
    OriginalList = TempList; // copy all items from temp list to original list.

0

এখানে একটি দক্ষ শাফলার যা বদলে যাওয়া মানগুলির একটি বাইট অ্যারে প্রদান করে। এটি কখনই প্রয়োজনের চেয়ে বেশি পরিবর্তিত হয় না। আগে যেখানে ছেড়ে গিয়েছিল সেখান থেকে এটি আবার শুরু করা যেতে পারে। আমার আসল বাস্তবায়ন (দেখানো হয়নি) এমন একটি এমইএফ উপাদান যা কোনও ব্যবহারকারীর নির্দিষ্ট প্রতিস্থাপনের শাফলারকে অনুমতি দেয়।

    public byte[] Shuffle(byte[] array, int start, int count)
    {
        int n = array.Length - start;
        byte[] shuffled = new byte[count];
        for(int i = 0; i < count; i++, start++)
        {
            int k = UniformRandomGenerator.Next(n--) + start;
            shuffled[i] = array[k];
            array[k] = array[start];
            array[start] = shuffled[i];
        }
        return shuffled;
    }

`


0

এটি করার জন্য এখানে থ্রেড-নিরাপদ উপায়:

public static class EnumerableExtension
{
    private static Random globalRng = new Random();

    [ThreadStatic]
    private static Random _rng;

    private static Random rng 
    {
        get
        {
            if (_rng == null)
            {
                int seed;
                lock (globalRng)
                {
                    seed = globalRng.Next();
                }
                _rng = new Random(seed);
             }
             return _rng;
         }
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
    {
        return items.OrderBy (i => rng.Next());
    }
}

0
 public Deck(IEnumerable<Card> initialCards) 
    {
    cards = new List<Card>(initialCards);
    public void Shuffle() 
     }
    {
        List<Card> NewCards = new List<Card>();
        while (cards.Count > 0) 
        {
            int CardToMove = random.Next(cards.Count);
            NewCards.Add(cards[CardToMove]);
            cards.RemoveAt(CardToMove);
        }
        cards = NewCards;
    }

public IEnumerable<string> GetCardNames() 

{
    string[] CardNames = new string[cards.Count];
    for (int i = 0; i < cards.Count; i++)
    CardNames[i] = cards[i].Name;
    return CardNames;
}

Deck deck1;
Deck deck2;
Random random = new Random();

public Form1() 
{

InitializeComponent();
ResetDeck(1);
ResetDeck(2);
RedrawDeck(1);
 RedrawDeck(2);

}



 private void ResetDeck(int deckNumber) 
    {
    if (deckNumber == 1) 
{
      int numberOfCards = random.Next(1, 11);
      deck1 = new Deck(new Card[] { });
      for (int i = 0; i < numberOfCards; i++)
           deck1.Add(new Card((Suits)random.Next(4),(Values)random.Next(1, 14)));
       deck1.Sort();
}


   else
    deck2 = new Deck();
 }

private void reset1_Click(object sender, EventArgs e) {
ResetDeck(1);
RedrawDeck(1);

}

private void shuffle1_Click(object sender, EventArgs e) 
{
    deck1.Shuffle();
    RedrawDeck(1);

}

private void moveToDeck1_Click(object sender, EventArgs e) 
{

    if (listBox2.SelectedIndex >= 0)
    if (deck2.Count > 0) {
    deck1.Add(deck2.Deal(listBox2.SelectedIndex));

}

    RedrawDeck(1);
    RedrawDeck(2);

}

2
স্ট্যাক ওভারফ্লোতে স্বাগতম! কোডের একটি বিশাল ব্লক না করে দয়া করে আপনার উত্তরে কিছু ব্যাখ্যা যুক্ত করে বিবেচনা করুন। আমাদের লক্ষ্য এখানে লোকদের শিক্ষিত করা যাতে তারা উত্তরটি বুঝতে পারে এবং এটি অন্যান্য পরিস্থিতিতে প্রয়োগ করতে পারে। আপনি যদি নিজের কোডটিতে মন্তব্য করেন এবং কোনও ব্যাখ্যা যোগ করেন, আপনি কেবল নিজের উত্তরটি আরও সহায়ক করে তুলবেন কেবলমাত্র এই বারের মতো প্রশ্ন করা ব্যক্তির পক্ষে নয়, ভবিষ্যতে যে কারও জন্য একই সমস্যা রয়েছে to
স্টারস্প্লসপ্লস

4
এই কোডটির বেশিরভাগই প্রশ্নের সাথে সম্পূর্ণ অপ্রাসঙ্গিক, এবং একমাত্র দরকারী অংশটি মূলত প্রায় 6 বছর আগে থেকেই অ্যাডাম টেগেনের উত্তরটি পুনরাবৃত্তি করে।
টিসি

0

স্বীকৃত উত্তরের একটি সাধারণ পরিবর্তন যা স্থানে কাজ করার পরিবর্তে একটি নতুন তালিকার প্রত্যাবর্তন করে এবং IEnumerable<T>অন্যান্য অনেক লিঙ্ক পদ্ধতি যেমন গ্রহণ করে তত বেশি সাধারণ গ্রহণ করে ।

private static Random rng = new Random();

/// <summary>
/// Returns a new list where the elements are randomly shuffled.
/// Based on the Fisher-Yates shuffle, which has O(n) complexity.
/// </summary>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> list) {
    var source = list.ToList();
    int n = source.Count;
    var shuffled = new List<T>(n);
    shuffled.AddRange(source);
    while (n > 1) {
        n--;
        int k = rng.Next(n + 1);
        T value = shuffled[k];
        shuffled[k] = shuffled[n];
        shuffled[n] = value;
    }
    return shuffled;
}


-5

পুরানো পোস্টটি অবশ্যই নিশ্চিত, তবে আমি কেবল একটি জিইউডি ব্যবহার করি।

Items = Items.OrderBy(o => Guid.NewGuid().ToString()).ToList();

একটি জিইউডি সর্বদা স্বতন্ত্র এবং যেহেতু এটি প্রতিবারই পুনরায় উত্পন্ন হয় ফলাফল প্রতিবার পরিবর্তিত হয়।


কমপ্যাক্ট, তবে কি আপনার কাছে ক্রমাগত নতুন গুডসকে উচ্চমানের এলোমেলোভাবে বাছাই করার বিষয়ে একটি রেফারেন্স রয়েছে? কুইড / ইউউইডের কয়েকটি সংস্করণে টাইম স্ট্যাম্প এবং অন্যান্য অ-এলোমেলো অংশ রয়েছে।
জোহান লন্ডবার্গ

8
এই উত্তর ইতিমধ্যে দেওয়া হয়েছে, এবং আরও খারাপ এটি এলোমেলো জন্য নয় ডিজাইন করা।
অ্যালেক্স আঙ্গাস

-7

এই ধরণের সমস্যার খুব সহজ পদ্ধতির তালিকায় তালিকার বেশ কয়েকটি এলোমেলো উপাদান অদলবদল ব্যবহার করা।

সিউডো-কোডে এটি দেখতে এরকম হবে:

do 
    r1 = randomPositionInList()
    r2 = randomPositionInList()
    swap elements at index r1 and index r2 
for a certain number of times

1
এই পদ্ধতির সাথে একটি সমস্যা হ'ল কখন থামবে knowing সিউডো-এলোমেলো নম্বর জেনারেটরে কোনও পক্ষপাত বাড়িয়ে তোলার প্রবণতাও এটির রয়েছে।
মার্ক বেসেসে

3
হ্যাঁ. অত্যন্ত অদক্ষ। এই জাতীয় পদ্ধতির ব্যবহার করার কোনও কারণ নেই যখন আরও সহজ, দ্রুত পদ্ধতির উপস্থিতিগুলিও ঠিক তত সহজ।
পিটারঅ্যালেন ওয়েবেবি

1
খুব দক্ষ বা কার্যকর নয় ... এটি এন বার চালানো সম্ভবত অনেকগুলি উপাদানকে তাদের আসল অবস্থানে রেখে যেতে পারে।
এনএসজোনাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.