Поиск элемента в списке

#c# #list #object #search #recursion

#c# #Список #объект #Поиск #рекурсия

Вопрос:

В C #, если у меня есть список объектов, где каждый список содержит список элементов списка, и каждый из этих элементов списка может быть списком объектов (или просто одним элементом списка), каков наилучший способ получения определенного списка по имени?

Каждый список и элемент списка имеют уникальное имя. Атрибутом типа в MapLocationListItem является либо «List», либо «ListItem».

Вот классы:

 public class MapLocationList
{
    public string name { get; set; }
    public List<MapLocationListItem> listItems { get; set;}

    public MapLocationList ()
    {
        listItems = new List<MapLocationListItem> ();
    }
}

public class MapLocationListItem
{
    public string name { get; set;}
    public string type { get; set;}
    public string heading { get; set;}
    public string subheading { get; set;}
    MapLocationList mapLocationList{ get; set;}
}
 

Заранее спасибо

Комментарии:

1. попробуйте использовать Linq и укажите, какой элемент вам нужно найти

2. Ваша модель выглядит немного странно для меня, у вас MapLocationList есть список MapLocationListItem ‘s, в котором есть список MapLocationList s?

Ответ №1:

То, что у вас здесь есть, — это дерево (с двумя типами узлов) (также предполагая, что у вас нет циклов, что сделало бы его графом). Обход дерева — довольно простая задача, которую мы можем решить в общем случае всего несколькими строками кода:

 public static IEnumerable<T> Traverse<T>(
    this IEnumerable<T> source
    , Func<T, IEnumerable<T>> childrenSelector)
{
    var stack = new Stack<T>(source);
    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;
        foreach (var child in childrenSelector(next))
            stack.Push(child);
    }
}
 

Итак, теперь, когда у нас есть a List<MapLocationList> , все, что нам нужно, это создать функцию, которая заставит все дочерние элементы любого данного узла использовать наш Traverse метод. Если бы у нас был только один тип узла, мы бы просто получили все дочерние узлы напрямую. Поскольку у нас есть два типа, нам нужно использовать SelectMany для получения дочерних элементов наших дочерних узлов:

 var allNodes = rootNodes.Traverse(mapLocations => 
    mapLocations.listItems.SelectMany(item => item.list));
 

Отсюда мы можем легко получить первый элемент с заданным именем:

 var servyNode = allNodes.FirstOrDefault(node => node.name == "Servy");
 

Ответ №2:

Найдите решение, как показано ниже, оно найдет и вернет MapLocationListItem в противном случае null (если не найдено)

     public class MapLocationList
    {
        public string name { get; set; }
        public List<MapLocationListItem> listItems { get; set; }

        public MapLocationList()
        {
            listItems = new List<MapLocationListItem>();
        }

        public MapLocationListItem findByName(string locationName)
        {
            MapLocationListItem findRes = listItems.Where(x => x.name.Equals(locationName)).FirstOrDefault();
            return findRes;
        }
    }

    public class MapLocationListItem
    {
        public string name { get; set; }
        public string type { get; set; }
        public string heading { get; set; }
        public string subheading { get; set; }
        MapLocationList list { get; set; }
    }
 

Комментарии:

1. Я полагаю, что запрашивающий также хочет выполнить повторный просмотр всех содержащихся в нем списков MapLocationListItem

Ответ №3:

вы можете использовать Linq :

    var res = from item in listItems
             where item.Name equals "yourentry"
             select item;
 

или просто :

 MapLocationListItem findRes = listItems.Where(x => x.name.Equals(yourentry)).FirstOrDefault();
 

Комментарии:

1. Я полагаю, что запрашивающий также хочет выполнить повторный просмотр всех содержащихся списков в MapLocationListItem..