如何在列表中访问随机项目?

我有一个数组列表,我需要能够点击一个按钮然后从列表中随机挑选一个字符串并显示在消息框中。

我该怎么做呢?

326953 次浏览

创建一个Random实例:

Random rnd = new Random();

获取一个随机字符串:

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

记住,如果你经常这样做,你应该重用Random对象。将它作为类中的静态字段,这样它只初始化一次,然后访问它。

  1. 在某处创建Random类的实例。请注意,不要在每次需要随机数时都创建一个新实例,这一点非常重要。您应该重用旧实例,以实现生成的数字的一致性。你可以在某个地方有static字段(注意线程安全问题):

    static Random rnd = new Random();
    
  2. Ask the Random instance to give you a random number with the maximum of the number of items in the ArrayList:

    int r = rnd.Next(list.Count);
    
  3. Display the string:

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

我通常使用这个扩展方法的小集合:

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

如果你只有一个数组列表,你可以强制转换它:

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

你可以:

list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()
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());

或者像这样简单的扩展类:

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>这样的索引集合或数组。

我已经使用这个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;
}

我需要更多的项目,而不仅仅是一个。所以,我写了这个:

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

为什么不:

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

为什么不[2]:

public static T GetRandom<T>(this List<T> list)
{
return list[(int)(DateTime.Now.Ticks%list.Count)];
}
从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);

我将建议不同的方法,如果列表中项目的顺序在提取时并不重要(并且每个项目应该只选择一次),那么您可以使用List而不是List,它是线程安全的无序对象集合:

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将尝试从无序集合中提取一个“随机”对象。