E_S
E_S

Reputation: 11

access the value of a random element of an list c#

I'm trying to access the value of a random element of an list. At the moment my code seems to be returning the element rather than the value.

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

at the moment if _randMoveDecider holds the values 2, 5 and 9 it will return 0, 1 or 2 rather than the values in the list, where am I going wrong?

[edit] I guess I should have said, the length of _randMoveDecider and the values stored in it change with each run through of the program, but they are always integers.

Upvotes: 0

Views: 214

Answers (4)

yamen
yamen

Reputation: 15618

How about just this?

// 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];

Even better, here's something that will randomise any list:

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

One way of using it in your scenario:

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

// then later
return randomiser.First();

Upvotes: 3

saeed sheikholeslami
saeed sheikholeslami

Reputation: 98

Simply add this extension class inside main class:

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

and then call it:

int value = mylist.randomOne();

EDIT: This is a test program that demonstrates how one would use the method. Note that due to incorrect usage of Random it produces very unbalanced results with more than 50 "random" numbers out of 100 being the same.

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

To fix the issue make Random static instance for Extension class or share more broadly in the program. This is discussed in 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)];
    }
}

Upvotes: 1

Lukasz Madon
Lukasz Madon

Reputation: 14994

Firstly you should initialize Random once. Make it a field:

private Random _rand = new Random();

Then get a random number from the proper range. if(x!=0) is useless - Next() returns numbersform <0, n) range

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

Upvotes: 2

Sprague
Sprague

Reputation: 1638

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

Upvotes: 0

Related Questions