I have an ArrayList, and I need to be able to click a button and then random开发者_JAVA百科ly pick out a string from that list and display it in a messagebox.
How would I go about doing this?
Create an instance of
Random
class somewhere. Note that it's pretty important not to create a new instance each time you need a random number. You should reuse the old instance to achieve uniformity in the generated numbers. You can have astatic
field somewhere (be careful about thread safety issues):static Random rnd = new Random();
Ask the
Random
instance to give you a random number with the maximum of the number of items in theArrayList
:int r = rnd.Next(list.Count);
Display the string:
MessageBox.Show((string)list[r]);
I usually use this little collection of extension methods:
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());
}
}
For a strongly typed list, this would allow you to write:
var strings = new List<string>();
var randomString = strings.PickRandom();
If all you have is an ArrayList, you can cast it:
var strings = myArrayList.Cast<string>();
You can do:
list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()
Or simple extension class like this:
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)];
}
}
Then just call:
myList.RandomElement();
Works for arrays as well.
I would avoid calling OrderBy()
as it can be expensive for larger collections. Use indexed collections like List<T>
or arrays for this purpose.
Create a Random
instance:
Random rnd = new Random();
Fetch a random string:
string s = arraylist[rnd.Next(arraylist.Count)];
Remember though, that if you do this frequently you should re-use the Random
object. Put it as a static field in the class so it's initialized only once and then access it.
Why not:
public static T GetRandom<T>(this IEnumerable<T> list)
{
return list.ElementAt(new Random(DateTime.Now.Millisecond).Next(list.Count()));
}
I'll suggest different approach, If the order of the items inside the list is not important at extraction (and each item should be selected only once), then instead of a List
you can use a ConcurrentBag
which is a thread-safe, unordered collection of objects:
var bag = new ConcurrentBag<string>();
bag.Add("Foo");
bag.Add("Boo");
bag.Add("Zoo");
The EventHandler:
string result;
if (bag.TryTake(out result))
{
MessageBox.Show(result);
}
The TryTake
will attempt to extract an "random" object from the unordered collection.
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());
I have been using this ExtensionMethod for a while:
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;
}
I needed to more item instead of just one. So, I wrote this:
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;
}
With this, you can get elements how many you want as randomly like this:
var _allItems = new List<TModel>()
{
// ...
// ...
// ...
}
var randomItemList = _allItems.GetSelectedRandom(10);
Printing randomly country name from JSON file.
Model:
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);
Why not[2]:
public static T GetRandom<T>(this List<T> list)
{
return list[(int)(DateTime.Now.Ticks%list.Count)];
}
精彩评论