如何避免将重复项添加到多层列表中

时间:2018-06-01 22:38:01

标签: c# asp.net asp.net-mvc linq asp.net-mvc-4

我有一个名为ITEMS的列表

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

因为Class ABC显示列表ITEMS可以有List<ABC> ChildList<ABC> Child可以有另一个List<ABC> Child。  这是个问题; 如果我想添加类型Class ABC的新项目来列出ITEMS,我如何确保它不在ITEMS列表或其内部子列表中,然后将其添加到ITEMS列表或其任何内部子列表?

最好的问候

2 个答案:

答案 0 :(得分:0)

使用扩展功能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,或者你有一个唯一的要添加的项目列表,从扁平的{{{ 1}}加快检查速度。

答案 1 :(得分:0)

向类添加递归方法,如下所示:

//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);

注意:上面的例子假设当他们的itemNames相等时,abc实例是相等的。当然,您可以修改标准,例如如果您希望引用相等,则abc.Equals(newAbc)已覆盖Equals()或abc == newAbc