Odpowiedzi:
Utwórz Random
gdzieś instancję klasy. Pamiętaj, że bardzo ważne jest, aby nie tworzyć nowej instancji za każdym razem, gdy potrzebujesz losowej liczby. Powinieneś ponownie użyć starej instancji, aby osiągnąć jednorodność wygenerowanych liczb. Możesz static
gdzieś mieć pole (uważaj na kwestie bezpieczeństwa wątków):
static Random rnd = new Random();
Poproś Random
instancję o podanie losowej liczby z maksymalną liczbą elementów w ArrayList
:
int r = rnd.Next(list.Count);
Wyświetl ciąg:
MessageBox.Show((string)list[r]);
Next(max)
połączenia jest wyłączne.
Zwykle używam tej małej kolekcji metod rozszerzenia:
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());
}
}
W przypadku silnie wpisanej listy pozwoli to na napisanie:
var strings = new List<string>();
var randomString = strings.PickRandom();
Jeśli wszystko, co masz, to ArrayList, możesz rzucić:
var strings = myArrayList.Cast<string>();
return list[rnd.Next(list.Count)];
Random
zamiast tego trzymanie instancji w stanie statycznym.
Możesz to zrobić:
list.OrderBy(x => Guid.NewGuid()).FirstOrDefault()
Utwórz Random
instancję:
Random rnd = new Random();
Pobierz losowy ciąg:
string s = arraylist[rnd.Next(arraylist.Count)];
Pamiętaj jednak, że jeśli często to robisz, powinieneś ponownie użyć Random
obiektu. Umieść go jako pole statyczne w klasie, aby było ono inicjowane tylko raz, a następnie dostęp do niego.
Lub prosta klasa rozszerzenia taka jak ta:
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)];
}
}
Następnie wystarczy zadzwonić:
myList.RandomElement();
Działa również dla tablic.
Unikałbym dzwonienia, OrderBy()
ponieważ może to być drogie w przypadku większych kolekcji. W List<T>
tym celu użyj indeksowanych kolekcji takich jak lub tablic.
IList
więc drugie przeciążenie nie jest konieczne.
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());
maxValue
parametrem metody Next
powinna być tylko liczba elementów na liście, a nie minus jeden, ponieważ zgodnie z dokumentacją „ maxValue jest wyłączną górną granicą liczby losowej ”.
Używam tego ExtensionMethod od dłuższego czasu:
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;
}
Zasugeruję inne podejście: jeśli kolejność elementów na liście nie jest ważna przy ekstrakcji (a każdy element powinien zostać wybrany tylko raz), to zamiast List
możesz użyć ConcurrentBag
bezpiecznej dla wątków, nieuporządkowanej kolekcji obiekty:
var bag = new ConcurrentBag<string>();
bag.Add("Foo");
bag.Add("Boo");
bag.Add("Zoo");
EventHandler:
string result;
if (bag.TryTake(out result))
{
MessageBox.Show(result);
}
TryTake
Będą próbować wyodrębnić „random” obiekt z kolekcji nieuporządkowanej.
Potrzebowałem więcej przedmiotu zamiast jednego. Więc napisałem to:
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;
}
Dzięki temu możesz uzyskać elementy, które chcesz tak losowo, jak to:
var _allItems = new List<TModel>()
{
// ...
// ...
// ...
}
var randomItemList = _allItems.GetSelectedRandom(10);
Drukowanie losowej nazwy kraju z pliku JSON.
Model:
public class Country
{
public string Name { get; set; }
public string Code { get; set; }
}
Implementacja:
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);
Dlaczego nie [2]:
public static T GetRandom<T>(this List<T> list)
{
return list[(int)(DateTime.Now.Ticks%list.Count)];
}