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

але у мене насправді немає мозку, щоб знати, як точно це написати ...: \ у мене є функція .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 Список itemsToDelete?
додано Автор dknaack, джерело
Власть предків не існує. Будь ласка, надайте більше вихідного коду.
додано Автор dknaack, джерело
@dknaack - ні, я хочу заповнити його каналами для видалення.
додано Автор Dementic, джерело
@BoltClock - додано в Q.
додано Автор Dementic, джерело
@ sq33G - проблема з моїм псевдонімом. Містить необхідність подання елемента, тоді як я хочу надати йому ідентифікатор елемента.
додано Автор Dementic, джерело
@ sq33G: Він, кажучи, що це псевдокод, привело мене вважати, що він не має такої власності. У своєму поспіху відповісти я пропустив, де сказав: "У мене є функція" Завжди ". Див мой відредагований відповідь.
додано Автор Merlyn Morgan-Graham, джерело
Який код для властивості предків ?
додано Автор BoltClock, джерело
Так, почекайте ... Якщо це те, що ви хочете зробити, що було з вашими елементами, «Видалити псевдокод»?
додано Автор sq33G, джерело
... чому ти кажеш, що предків немає, коли код (тепер) тут прямо на оригіналі? (звідси внизу)
додано Автор sq33G, джерело
Тепер я великий шанувальник LINQ і все це, але я не думаю, що це слід вважати єдиним способом вирішення переліку проблем. Набагато більш оптимальним рішенням буде використання видобутку, а не побудова деякого збігу або списку, повернути його назад і повернутися, див. Відповідь @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 для об'єктів (на відміну від Linq для SQL або Linq для об'єктів), створіть властивість Parent на MyClass правильного типу, а не намагаючись зв'язати їх за допомогою Id .

Тоді ви можете зробити властивість предків досить легко:

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 для об'єктів, створіть властивість навігації типу MyClass , щоб перейти до батьківського класу, і виконайте те ж саме. Зауважте, що це може призвести до повторних запитів. Не впевнений, що Linq може перейти на ієрархічний запит.

2
додано
у мене є предки, батько та діти. мені просто потрібно знати, як вибрати всі класи, які містять певний клас.
додано Автор Dementic, джерело
+1, щоб побити мене до нього, поки я набираю :)
додано Автор edvaldig, джерело

Ось як я це зробив би, використовуючи метод hashset і RemoveAll.

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

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

1
додано
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug