2009-05-06 11 views
5

Mam słownik i listę kluczy do usunięcia ze słownika. To jest teraz moja implementacja:Jak używać LINQ do "przycinania" słownika?

var keys = (from entry in etimes 
      where Convert.ToInt64(entry.Value) < Convert.ToInt64(stime) 
      select entry.Key).ToList(); 

foreach (var key in keys) 
{ 
    etimes.Remove(key); 
    count--; 
} 

Czy jest coś, co mogę zrobić, aby wyeliminować pętlę foreach?

+1

Przy okazji nie potrzebowałeś .ToList() foreach będzie działał z każdym IEnumerable –

+0

LINQ to język zapytań, który może tworzyć nowe dane poprzez transformację istniejących danych. Nie można zmienić istniejących danych. – codymanix

Odpowiedz

6
var pruned = etimes.Where(entry => Convert.ToInt64(entry.Value) >= 
    Convert.ToInt64(stime)).ToDictionary(entry => entry.Key, 
     entry => entry.Value); 

Stwierdzenie to po prostu filtruje słownika przy użyciu funkcji LINQ Where wybrać, które elementy do zachować raczej niż do usunięcia (które następnie wymaga dalszego kodu, jak to pokazał). ToDictionary zamienia thwe IEnumerable<KeyValuePair<TKey, TValue>> na pożądany typ Dictionary<TKey, TValue> i jest co najmniej całkiem prosty, jeśli nie przerażająco elegancki lub wydajny ze względu na konieczność określenia dwóch wyrażeń lambda, aby wybrać klucz i wartość z KeyValuePair (a następnie utworzyć nowy słownik). Mówiąc to, nie uważam tego za problem, zwłaszcza jeśli słownik jest mały i/lub liczba usuniętych elementów jest duża.

+0

Nie chciałbym komentować wydajności przy okazji - jeśli się tym przejmujesz, przetestuj dwie metody. Nie jestem pewien, czy twoje oryginalne rozwiązanie wykorzystujące foreach będzie * o wiele * szybsze. – Noldorin

+0

Nie martwię się wydajnością, w słowniku jest tylko kilka kluczy w dowolnym momencie. Po prostu próbuję uzyskać lepszy uchwyt LINQ. Dzięki, działało to świetnie. – scottm

+0

Może to być znacznie droższe niż proste dla każdej pętli, ponieważ utworzy nowy słownik. I myślę, że to też nie poprawia czytelności. Tak więc po prostu trzymałbym się każdej pętli i mógłbym przenieść ją do metody (rozszerzenia), ale nie widzę żadnej wygranej dla rozwiązania LINQ. –

0

Cóż, problemy z wydajnością lub czytelności na bok, nie może to również zrobić coś jak następuje:

<Extension> void itemDelete(List l, object item) { 
    l.Remove(item) 
} 

var keys = (from entry in etimes 
     where Convert.ToInt64(entry.Value) < Convert.ToInt64(stime) 
     select entry.Key).ToList(); 

keys.foreach(itemDelete()); 

wybaczyć moje kodowanie, nie jestem 100% pewny dokładnej składni (zwłaszcza w C#); rozważ ten pseudokod. Zwróć uwagę na dodanie nowej funkcji i funkcji .foreach na końcu zapytania LINQ. Wiem, że byłoby to możliwe w VB, zakładam, że C# ma coś podobnego ... jeśli nie, zawsze możesz napisać własne rozszerzenie .foreach. Może coś ulepszyć lub nie, ale jest to pomysł.

+0

Przebacz mi, jeśli to głupie pytanie, ale czy utworzysz tę metodę rozszerzenia w częściowej klasie? Nadal staram się uporać z metodami Extension i jak z nich korzystać i je tworzyć. – Jagd

+0

@Jagd: Nie ma powodu, aby używać częściowej klasy. Zalecaną praktyką jest deklarowanie ich na własną rękę w ramach * klasy statycznej * i metod rozszerzenia grupy na klasy statyczne o podobnej funkcjonalności. – Noldorin

+0

W VB tworzysz je w modułach, więc ... Powiedziałbym, że słucham najlepszych praktyk Noldorina. – eidylon

Powiązane problemy