2012-05-18 4 views
8

Im используя следующий фрагмент кода для загрузки моего текстового файла в hashset.Получить случайный элемент из hashset?

HashSet<string> hashs = new HashSet<string>(File.ReadLines("textFile.txt")); 

Мне интересно, есть ли какой-либо простой способ получить от него случайную строку?

Если текст textFile.txt содержит 10 строк, я хотел бы рандомизировать и захватить одну из существующих линий.

+1

Что вы пробовали? Вы пытались использовать класс System.Random для генерации случайного числа между 0 и <# of lines>, а затем ссылаясь на этот элемент по индексу? Все эти задачи уже задокументированы в библиотеке MSDN. http://mattgemmell.com/2008/12/08/what-have-you-tried/ – David

ответ

10
Random randomizer = new Random(); 
string[] asArray = hashs.ToArray() 
string randomLine = asArray[randomizer.Next(asArray.length)]; 
+0

работает отлично! спасибо человеку – user1213488

+3

Довольно неэффективная производительность. Не то, чтобы я знал лучший способ, но просто сказал. – batman

2

Вы можете сгенерировать случайное число между 0 и размером набора, а затем выполнить итерацию по настройке до тех пор, пока не достигнете элемента, индекс которого совпадает с номером сгенерированного числа. Затем выберите этот пункт как случайный элемент

+0

как будет выглядеть код для этого? не уверен, как написать это :) – user1213488

+0

1. Google «System.Random». 2. Просмотрите уже предоставленные образцы документа и кода, доступные во всем Интернете. 3. Узнайте, а не используйте ответ «копировать/вставить». (Думаю, сегодня это один из моих «рывок» дней.) – David

1

Или, может быть, более общее решение для любого перечислимого

public static class RandomExtensions 
{ 
    private static readonly Random rnd = new Random(); 
    private static readonly object sync = new object(); 

    public static T RandomElement<T>(this IEnumerable<T> enumerable) { 
     if (enumerable == null) 
      throw new ArgumentNullException("enumerable"); 

     var count = enumerable.Count(); 

     var ndx = 0; 
     lock (sync) 
      ndx = rnd.Next(count); // returns non-negative number less than max 

     return enumerable.ElementAt(ndx); 
    } 
} 
+0

'ElementAt' будет генерировать исключение для пустой коллекции. –

+2

@ lazyberezovsky Если ElementAt выбрасывает, то RandomElement также должен вызывать одно и то же исключение. Там должен быть RandomElementOrDefault, в этом случае – Vasea

24

простой ответ, как принято одно можно без перечисляя весь массив каждый раз, когда:

private static readonly Random  random = new Random(); 
private static readonly HashSet<T> hashset = new HashSet<T>(); 

... 

T element = hashset.ElementAt(random.Next(hashset.Count)); 
+6

ElementAt по-прежнему перечисляет элементы до тех пор, пока не достигнет указанного индекса, поэтому он не будет стремительно ускоряться. – Zonko