2012-05-01 45 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