Как избежать добавления дублированного элемента в список из нескольких слоев - PullRequest
0 голосов
/ 02 июня 2018

У меня есть список под названием ITEMS следующего типа

public class ABC
(
    string itemName{get;set;}
    int parentID{get;set;}
    List<ABC> Child {get;set;}    
)

Так как Class ABC показывает, список List ITEMS может иметь List<ABC> Child, а List<ABC> Child может иметь еще List<ABC> Child.Вот вопрос;Если я хочу добавить новый элемент типа Class ABC в список ITEMS, как я могу убедиться, что его нет в списке ITEMS или в его списках Inner Child, а затем добавить его в список ITEMS или любой из его внутренних дочерних списков?

С наилучшими пожеланиями

Ответы [ 2 ]

0 голосов
/ 02 июня 2018

Добавьте рекурсивный метод к классу, например так:

//using System.Linq;

public class ABC
(
    string itemName{get;set;}
    int parentID{get;set;}
    List<ABC> Child {get;set;}    

    public bool AlreadyContains(ABC abc)
    {
        if (Child.Any( a => a.itemName == abc.itemName )) return true;  //Check children
        return Child.Any( a => a.AlreadyContains(abc) );   //Ask children to check their children too
    }
)

Затем вы можете проверить с помощью одной строки кода:

if (!abc.AlreadyContains(newAbc)) abc.Add(newAbc);

Примечание. В приведенном выше примере предполагается, что abcэкземпляры равны, когда их itemNames равны.Конечно, вы можете изменить критерии, например, abc.Equals(newAbc), если у вас есть переопределенный метод Equals (), или abc == newAbc, если вы хотите ссылочное равенство.

0 голосов
/ 02 июня 2018

Использование функции расширения Flatten:

public static IEnumerable<T> Flatten<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> flattenFn) => e.SelectMany(c => c.Flatten(flattenFn));
public static IEnumerable<T> Flatten<T>(this T current, Func<T, IEnumerable<T>> childrenFn) {
    var working = new Stack<T>();
    working.Push(current);

    while (working.Count > 0) {
        current = working.Pop();
        yield return current;

        if (childrenFn(current) != null)
            foreach (var child in childrenFn(current))
                working.Push(child);
    }
}

Вы можете сгладить оригинал ITEMS List, а затем проверить, нет ли в нем нового элемента:

var exists = ITEMS.Flatten(x => x.Child).Select(x => x.itemName).Contains(newItemID);

Если вы делаете это много, может быть целесообразно рассмотреть структуру на основе хеша, такую ​​как Dictionary или, если у вас есть уникальный список элементов для добавления, создайте хеш-набор из сглаженного ITEMS дляускорить проверку.

...