Linq - selecteer waar voorouders dit bevatten?

soms voel ik me dom ...

ik heb een eenvoudige les:

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

en ik heb een lijst die de klasse bevat:

List myItems = new List

verderop in de code voer ik de lijst met klassen in.

nu wil ik een item uit de lijst verwijderen. maar omdat een item kinderen en kleinkinderen kan hebben enz ... ik wil alles verwant verwijderen ..

dacht aan zoiets als: (pseudo-code)

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

maar ik heb niet echt de hersens atm om te weten hoe ik het precies moet schrijven ...: \ ik heb de functie .Ancestors ... heb gewoon hulp nodig met de 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
Wilt u de inhoud van var List itemsToDelete verwijderen?
toegevoegd de auteur dknaack, de bron
De eigenschap Voorouders bestaat niet. Geef meer broncode op.
toegevoegd de auteur dknaack, de bron
@ dknaack - nee, ik wil het vullen met de kanalen om te verwijderen.
toegevoegd de auteur Dementic, de bron
@BoltClock - toegevoegd aan Q.
toegevoegd de auteur Dementic, de bron
@ sq33G - het probleem met mijn pseucode is .Contains moeten een item worden ingevoerd, terwijl ik het een ID van een item wil geven.
toegevoegd de auteur Dementic, de bron
@ sq33G: Hem zeggen dat het een pseudo-code was, bracht mij ertoe te geloven dat hij niet zo'n eigenschap had. In mijn haast om te antwoorden, miste ik waar hij zei: "Ik heb de functie .Ancestors". Zie mijn bewerkte antwoord.
toegevoegd de auteur Merlyn Morgan-Graham, de bron
Wat is de code voor de eigenschap Voorouders ?
toegevoegd de auteur BoltClock, de bron
Dus wacht even ... Als dit is wat u wilt doen, wat was er mis met uw itemsToDelete pseudocode?
toegevoegd de auteur sq33G, de bron
... waarom zeg je dat er geen Voorouders zijn als de code (precies) daar op de originele post staat? (vandaar downvote)
toegevoegd de auteur sq33G, de bron
Nu ben ik een grote fan van LINQ en zo, maar ik denk niet dat dit de enige manier is om een ​​aantal problemen op te lossen. Een veel optimalere oplossing zou het gebruik van rendement zijn in plaats van het bouwen van een hashset of lijst, het omdraaien en terugkeren, zie het antwoord van @ Morganlyn Graham
toegevoegd de auteur edvaldig, de bron

2 antwoord

Ik heb je vraag opnieuw gelezen, vooral het laatste deel waar je zei dat je al .Ancestors hebt, en nu is het logischer.

Doe dit om uw lijst met te verwijderen items te bekijken:

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

Vervolgens kunt u foreach door het resultaat halen en ze uit de oorspronkelijke lijst verwijderen.

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.

Voor bewerking:

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.

Maar hier is hoe te bereiken wat u probeert te bereiken:

Als u Linq to Objects gebruikt (in tegenstelling tot Linq to SQL of Linq to Entities), maakt u een eigenschap met de naam Parent op MyClass , van het juiste type, in plaats van proberen om ze te linken met Id .

Dan kunt u een eigenschap Voorouders vrij eenvoudig maken:

public IEnumerable Ancestors
{
    get
    {
        MyClass current = this;

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

Als u de klasse niet kunt bewerken, maakt u een uitbreidingsmethode met de naam GetAncestors .

Dan kun je iets gebruiken dat erg lijkt op de code die je in je vraag hebt geschreven:

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

Linq to Entities

Als u Linq voor entiteiten gebruikt, maakt u een navigatie-eigenschap van het type MyClass om naar het bovenliggende element te navigeren en hetzelfde te doen. Houd er rekening mee dat dit re-query's kan veroorzaken. Weet niet zeker of de Linq kan of zou worden vertaald in een hiërarchische query.

2
toegevoegd
ik heb voorouders en ouder en kinderen. ik moet alleen weten hoe ik alle klassen moet selecteren die de specifieke klasse bevatten.
toegevoegd de auteur Dementic, de bron
+1 om me ertegen te slaan terwijl ik aan het typen was :)
toegevoegd de auteur edvaldig, de bron

Dit is hoe ik het zou doen met een hashset- en RemoveAll-methode.

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

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

1
toegevoegd