2012-05-01 42 views
0

我試圖訪問列表中的隨機元素的值。目前我的代碼似乎正在返回元素而不是值。訪問列表中的隨機元素的值c#

int x = _randMoveDecider.Count; 

//makes sure x is never more than the array size 
if(x != 0) 
    { 
    x = x - 1 ; 
    } 

Random _r = new Random(); 

_move = _r.Next(_randMoveDecider[x]); 

return _randMoveDecider[_move]; 

在如果_randMoveDecider持有值2,5和9它將返回的那一刻0,1或2,而不是在列表中的值,我要去哪裏錯了?

我想我應該說,_randMoveDecider的長度和存儲在其中的值隨程序的每次運行而改變,但它們總是整數。

+0

什麼是在randMoveDecider ??? –

+0

值改變,但它們總是整數。 –

回答

2

首先你應該初始化Random一次。使它成爲一個領域:

private Random _rand = new Random(); 

然後從合適的範圍內獲得一個隨機數。如果(!X = 0)是沒有用的 - 下()返回numbersform < 0,N)範圍

return _randMoveDecider[_rand.Next(_randMoveDecider.Count)]; 
+0

@yamen編號從文檔「返回小於指定最大值的非負隨機數」。 –

+0

是的,我剛剛意識到這是最大的獨家,刪除評論。 – yamen

3

如何只呢?

// as a field somewhere so it's initialised once only 
public Random _r = new Random(); 

    // later in your code 
var _randList = new List<int>{4,5,8,9}; 
var _move = _r.Next(_randList.Count); 
return _randList[_move]; 

更妙的是,這裏的東西,將隨機化的任何列表:

public static Random _rand = new Random(); 

public IEnumerable<T> Randomise<T>(IList<T> list) 
{ 
    while(true) 
    { 
     // we find count every time since list can change 
     // between iterations 
     yield return list[_rand.Next(list.Count)]; 
    } 
} 

一個在方案中使用它的方式:

// make this a field or something global 
public IEnumerbale<int> randomiser = Randomise(_randList); 

// then later 
return randomiser.First(); 
+0

-1。創建隨機每次將傳統上返回相同的值,直到時間變​​化... –

+0

@AlexeiLevenkov我已經在第二組代碼中修復,而不是第一組,現在更新。這不是-1值得.. – yamen

+0

你沒有真正解決這個問題 - 如果你爲2個列表創建Randomise,並比較產生的「隨機化」序列,你會發現幾乎所有的時間都是以相同的方式隨機化。您正在創建隨機可能使用相同的種子進行初始化(如果在大約相同的時間 - 即在下一行中調用) - 每個列表 - 結果是僞隨機序列具有相同的高概率。 –

1

只需添加主類,這裏面的擴展類:

public static class Extensions 
{ 
    public static int randomOne(this List<int> theList) 
    { 
     Random rand = new Random(DateTime.Now.Millisecond); 
     return theList[rand.Next(0, theList.Count)]; 
    } 
} 

然後調用它:

int value = mylist.randomOne(); 

編輯:這是一個測試程序,演示如何使用該方法。請注意,由於Random的使用不正確,它會產生非常不平衡的結果,100個以上的50個「隨機」數字是相同的。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var myList = Enumerable.Range(0, 100).ToList(); 
     var myRandoms = myList.Select(v => new { key = v, value = 0 }) 
       .ToDictionary(e => e.key, e => e.value); 

     for (int i = 0; i < 100; i++) 
     { 
      var random = myList.RandomOne(); 
      myRandoms[random]++; 
     } 

     Console.WriteLine(myRandoms.Values.Max()); 
     Console.ReadLine(); 
    } 
} 

要解決該問題,請在Extension程序中使用隨機靜態實例或在程序中更廣泛地共享。這在FAQ for Random中討論。

public static class Extensions 
{ 
    static Random rand = new Random(); 
    public static int randomOne(this List<int> theList) 
    { 
     return theList[rand.Next(0, theList.Count)]; 
    } 
} 
+0

-1。這是確切的代碼,如何不使用隨機類。 –

+0

你之前嘗試過嗎? –

+0

我做到了。請參閱編輯中的示例,其中包括修復您的擴展程序 –

0
var random = new Random(); 
var item = list.ElementAt(random.Next(list.Count())); 
+0

你可以直接調用list indexer'list [index]'而不用調用擴展方法,它會做幾個檢查,轉換,最後調用list索引器。 –

+0

我故意這樣做,但可以看到你的觀點。我這樣做是因爲我正在編程到IEnumerable接口,而不是一個具體的類型。 http://stackoverflow.com/questions/5326874/why-would-i-use-enumerable-elementat-versus-the-operator。如果海報使用IList,則比方法調用花費的開銷要少(還要注意原始海報沒有指定數據類型。) – Sprague