Перебирать списки, чтобы найти атрибут name

#c# #list #object #recursion #find

#c# #Список #объект #рекурсия #Найти

Вопрос:

Какой наилучший способ в C # найти имя объекта, вложенного в список?

Вот мои классы:

 public class ItemListGallery
{
    public string name { get; set; }
    public List<ItemList> ListItems { get; set; }
}

public class ItemList
{
    public string name { get; set; }
    public List<Item> items { get; set; }
}

public class Item
{
    public string name { get; set; }
}
  

Если у меня есть List<ItemListGallery> , и каждый элемент в List<ItemListGallery> имеет List<ItemList> , и каждый элемент в List<ItemList> имеет Item , и у меня есть name значение, которое нужно найти, как я могу вернуть объект / список с определенным name значением?

Каждый атрибут name уникален.

Я пытался написать какой-нибудь код поиска, но заблудился. Есть ли расширенная функция IEnumerable, которую я могу использовать, чтобы помочь в этой ситуации?

Могу ли я, пожалуйста, получить некоторую помощь с этим?

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

Редактировать

Вот код поиска, который я пытаюсь написать, правильный ли это подход?

 public class ItemListGallery
{
    public string name { get; set; }
    public List<ItemList> ListItems { get; set; }

    public string Find(string name)
    {
        foreach (var item in ListItems) 
        {
            if (item.Find(name) != null) 
            {
                return name;
            }
        }
        return null;
    }
}

public class ItemList
{
    public string name { get; set; }
    public List<Item> items { get; set; }

    public string Find(string name)
    {
        foreach (var item in items) 
        {
            if (item.name != null) 
            {
                return name;
            }
        }
        return null;
    }
}

public class Item
{
    public string name { get; set; }
}
  

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

1. Вы говорите, что написали какой-то код, но не предоставили им общий доступ. Обновите вопрос недостающим кодом.

2. Вы хотите найти ItemListGallery, содержащий список<ItemList>, в котором есть элемент с этим именем? Или вам нужен список<ItemList> ?

3. это имя, которое вы хотите отфильтровать, принадлежит вашему списку или элементу?

Ответ №1:

Вы можете расставить точки над ним двумя способами. Либо вы используете отражение, либо используете общий вспомогательный интерфейс. В любом случае, ListItems и items должны иметь одинаковое имя, чтобы обеспечить некоторую логику отношения.

 public List<Item> ListItems { get; set; }

public List<ItemList> ListItems { get; set; }
  

Вот способ, которым вы можете сделать это с помощью общего интерфейса

 public interface IItem 
{
    String Name { get; set; }
}

public interface IContainerItem
{
    List<IItem > ListItems { get; }
}
  

Затем :

 public class ItemListGallery : IContainerItem, IItem

..... 


public class ItemList: IContainerItem, IItem 

.....

public class Item : IItem 
  

Тогда вот как вы можете получить его рекурсивно :

 private static IItem DoSearch(List<IItem> rootItems, String name) {
    foreach (var item in rootItems) { 

        if (item.Name == name){
            return item ; 
        } 

        if (item is IContainerItem) {

            var containerItem = (IContainerItem) item; 

            var result = DoSearch(containerItem .ListItems , name) ; 

            if (result != null) {
                return result ; 
            }
        }
    } 

    return null ; 
}
  

Ответ №2:

Самым простым в использовании является LINQ.

Задан параметр поиска с именем findStr . Давайте предположим, что вы хотите найти любой ItemListGallery объект с именем findStr , или содержащий ItemList объект с именем findStr , или содержащий ItemList , который содержит Item named findStr … вы можете сделать это таким образом:

 var findqry = 
    (
        from gal in galleryList
        where 
            gal.name == findStr ||
            gal.ListItems.Any(li => 
                li.name == findStr || 
                li.Items.Any(i => i.name == findStr)
            )
        select gal
    );
  

Если вам нужен только один результат, findqry.FirstOrDefault() мы предоставим его вам. Если вам нужны все результаты, findqry.ToList() or findqry.ToArray() вернет их все.

Обратите внимание, что выполнение этого в LINQ to Objects приведет к сравнениям с учетом регистра, как и при любом другом использовании == с string s. LinqToSql, с другой стороны, будет выполнять сравнения с учетом или без учета регистра в зависимости от параметров сортировки сравниваемого поля / таблицы / базы данных.

Если вы хотите выполнять сравнения без учета регистра, используйте string.Compare(object.name, findStr, true) == 0 или аналогичный вместо object.name == findstr .

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

1. Было бы неплохо немного критики, если вы собираетесь отклонить ответ. Просто говорю.