Linq - 选择祖先包含的位置?

时间:2011-10-27 20:13:35

标签: c# linq lambda

有时,我只是觉得愚蠢......

我有一个简单的课程:

public class myClass
{
    public long Id { get; set; }
    public long ParentChannelId { get; set; }
}

我有一个包含类的列表:

List<myClass> myItems = new List<myClass>

在代码的下方,我用列表提供列表。

现在,我想从列表中删除一个项目。 但是,因为一件物品可以有孩子和孙子等... 我想删除所有相关的内容..

想到的是: (伪代码)

var List<myClass> itemsToDelete = myItems.Where(i => i.Ancestors.Contains(myItemId));

但是我真的没有大脑知道如何写出来......:\ 我确实有.Ancestors功能...... 只需要帮助lambda linq

public List<Channel> Ancestors
{
    get
    {
        List<MyCms.Content.Channels.Channel> result = new List<MyCms.Content.Channels.Channel>();

        Channel channel = this;

        while (channel != null)
        {
            result.Add(channel);
            channel = myChannels.Where(c => c.ParentChannelId == this.Id).First();
        }
        result.Reverse();

        return result;
    }
}

编辑:我想我没有解释自己应该...... 我有所有的属性,如祖先,儿童父母等... 我想选择可能包含特定类的所有类...

2 个答案:

答案 0 :(得分:2)

我已经重新阅读了您的问题,尤其是您说过您已经拥有.Ancestors的最后一部分,现在它更有意义。

执行此操作以获取要删除的项目列表:

List<MyClass> itemsToDelete = myItems
    .Where(i => i.Id == myItemId)
    .SelectMany(i => i.Ancestors)
    .Concat(myItems) // Want to delete these too, not just the ancestors
    .ToList()
    ;

然后您可以foreach完成结果,并将其从原始列表中删除。

我建议将这些内容保存在Dictionary<int, MyClass>HashSet<MyClass>而不是列表中,因为删除会更快方式

对于HashSet,您必须实施EqualsGetHashCode,或创建IEqualityComparer<MyClass>实施以提供这些方法。

编辑前:

我不会这样写我的代码。我只是创建一个Dictionary<int, MyClass>而不是列表。它将比涉及祖先/树遍历的任何内容更快地执行查找。

但这是如何完成你想要完成的事情:

如果您正在使用Linq to Objects(而不是Linq to SQL或Linq to Entities),请在Parent上创建一个名为MyClass的属性,其类型正确,而不是尝试链接他们是Id

然后您可以非常轻松地创建Ancestors属性:

public IEnumerable<MyClass> Ancestors
{
    get
    {
        MyClass current = this;

        while(current != null)
        {
            current = current.Parent;
            yield return current;
        }
    }
}

如果您无法编辑课程,请制作名为GetAncestors的扩展程序。

然后你可以使用与你在问题中写的代码非常相似的东西:

List<MyClass> itemsToDelete = myItems
    .Where(i => i.Ancestors.Any(a => a.Id == myItemId))
    .ToList();

Linq to Entities

如果您使用Linq to Entities,请创建类型MyClass的导航属性以导航到父级,并执行相同的操作。请注意,这可能会导致重新查询。不确定Linq是否可以或将被翻译成分层查询。

答案 1 :(得分:1)

这就是我使用hashset和RemoveAll方法的方法。

var itemsToDelete = new HashSet<myClass>(otherItems);
myItems.RemoveAll(i => itemsToDelete.Contains(i));

删除所有方法
http://msdn.microsoft.com/en-us/library/wdka673a.aspx