Как найти случайный элемент из списка C #, который имеет определенное значение? - PullRequest
1 голос
/ 26 марта 2019

Я пытаюсь найти элемент из списка, который имеет поле с определенным значением; некоторые записи будут иметь одинаковое значение для этого поля, и в этом случае я бы хотел вернуть одну из них в случайном порядке. Функция List.Find возвращает один случайным образом, если есть несколько записей, которые удовлетворяют критериям? Код ниже - это то, что у меня сейчас есть; если он используется в одном и том же списке несколько раз, будет ли он возвращать одну и ту же запись каждый раз, если несколько удовлетворяют критериям? Этот список достаточно велик, и я предпочел бы не разбираться с ним, составить список всего, что соответствует критериям, а затем случайным образом вернуть один из них; Я надеюсь найти более эффективный способ. Если это невозможно для Списка, существует ли другая структура данных, более подходящая для этого?

public List<Category> Categories {get; set;}

public Category CatByName(string nm)
        {
            string name = nm.ToUpper();
            return Categories.Find(x => x.CategoryName.Contains(name));
        }

Ответы [ 2 ]

3 голосов
/ 26 марта 2019

Краткий ответ: нет, вы должны перебирать список.

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

Что бы я предложил сделать, это собрать все соответствующие элементы в список, а затем взять случайный индекс. Я нахожу это более читабельным и менее запутанным, чем сортировка по случайному числу.

public Category CatByName(string nm)
{
    string name = nm.ToUpper();
    var matching = Categories.Where(x => x.CategoryName.Contains(name)).ToList();
    if (matching.Count == 0)
    {
       return null;
    }
    Random rnd = new Random();
    return matching[rnd.Next(matching.Count)];
}
1 голос
/ 26 марта 2019

Поскольку Find будет работать только на List<T>, вы также можете использовать Where, что применимо к IEnumerable<T>

Random rnd = new Random();
var selected = Categories.Where(x => x.CategoryName.Contains(nm.ToUpper()));
var item = selected.Skip(rnd.Next(selected.Count()).FirstOrDefault();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...