Linq - 先祖がこれを含む場所を選択しますか?

時々、私はただ気が気になる...

私は簡単なクラスを持っています:

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

私はクラスを含むリストを持っています:

List myItems = new List

さらにコードの下で、私はクラスでリストをフィードします。

今、私はリストから項目を削除したい。 しかし、アイテムは子供や孫などを持つことができるので... 私はすべての関連を削除したい..

次のようなことを考えていた: (擬似コード)

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

しかし、私は本当にそれを正確に書く方法を知るために頭脳atmを持っていない:... \ 私は .Ancestors 関数を持っています... ちょうどlambda linqの助けが必要

public List Ancestors
{
    get
    {
        List result = new List();

        Channel channel = this;

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

        return result;
    }
}

EDIT: guess i did not explain myself as i should... i have all the properties like ancestors, children parent etc... i want to select all the classes that might contain the specific class...

0
var List itemsToDeleteの内容を削除しますか?
追加された 著者 dknaack,
Ancestorsプロパティは存在しません。より多くのソースコードを提供してください。
追加された 著者 dknaack,
@ dknaack - いいえ、私は削除するチャンネルでそれを埋めるしたい。
追加された 著者 Dementic,
@BoltClock - Qに追加されました。
追加された 著者 Dementic,
@ sq33G - 私のpseucodeの問題です。アイテムのIDをフィードしたいのですが、そのアイテムにフィードを与える必要があります。
追加された 著者 Dementic,
@ sq33G:彼はそれが偽コードだったと言って、私は彼がそのような財産を持っていなかったと信じていました。答えが急いで、「私は.Ancestors関数を持っている」と言いました。私の編集された答えを見てください。
追加された 著者 Merlyn Morgan-Graham,
Ancestors プロパティのコードは何ですか?
追加された 著者 BoltClock,
だから待ってください...これがあなたがしたいことなら、itemsToDelete擬似コードで何が間違っていましたか?
追加された 著者 sq33G,
...元の投稿にコードが(今)あると、なぜ祖先はいないと言いますか? (したがって、下向き)
追加された 著者 sq33G,
今私はLINQとそのすべてのファンですが、私はそれが列挙可能な問題を解決する唯一の方法と考えられるべきではないと思います。はるかに最適な解決策は、いくつかのハッシュセットやリストを構築し、それを逆にして戻すのではなく、yieldを使用することです。@Merlyn Morgan-Grahamの答えを見てください
追加された 著者 edvaldig,

2 答え

私はあなたの質問、特に .Ancestors を持っていると言った最後の部分をもう一度読んだので、もっと意味があります。

削除するアイテムのリストを取得するには、これを行います:

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

次に結果を foreach して元のリストから削除します。

I'd suggest keeping these in a Dictionary or a HashSet instead of a list, since removal will be way faster.

For a HashSet, you'll have to implement Equals and GetHashCode, or create an IEqualityComparer implementation to provide those methods.

編集前:

I wouldn't write my code this way. I'd simply create a Dictionary instead of a list. It will do a lookup way faster than anything involving ancestors/tree traversal.

しかし、達成しようとしていることを達成する方法はここにあります:

Linq to ObjectsまたはLinq to Entitiesとは対照的に、Linq to Objectsを使用している場合は、正しいタイプの MyClassParent というプロパティを Id でそれらをリンクしようとしています。

それで、 Ancestors プロパティをかなり簡単に作ることができます:

public IEnumerable Ancestors
{
    get
    {
        MyClass current = this;

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

クラスを編集できない場合は、 GetAncestors という拡張メソッドを作成します。

次に、あなたの質問に書いたコードに非常によく似た何かを使うことができます:

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

エンティティへのLinq

Linq to Entitiesを使用している場合は、 MyClass 型のナビゲーションプロパティを作成して親に移動し、同じことをします。これにより、再クエリが発生する可能性があることに注意してください。 Linqが階層クエリに変換できるかどうかは不明です。

2
追加された
私は祖先と親と子どもがいます。私はちょうど特定のクラスを含むすべてのクラスを選択する方法を知る必要があります。
追加された 著者 Dementic,
私が入力している間に私にそれを打つための+1 :)
追加された 著者 edvaldig,

これは、私がハッシュセットとRemoveAllメソッドを使って行う方法です。

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

RemoveAll Method
http://msdn.microsoft.com/en-us/library/wdka673a.aspx

1
追加された