2012-10-20 12 views
33

Mam niektóre listy (gdzie T jest niestandardową klasą, a klasa ma niektóre właściwości). chciałbym wiedzieć jak zmienić jedną lub więcej wartości inide z nim za pomocą Lambda wyrażeń, więc wynik będzie taki sam, jak w pętli foreach poniżej:Zmienić niektóre wartości wewnątrz listy <T>

UWAGA: Lista ta zawiera wiele elementów wewnątrz (kilka wierszy)

 foreach (MyClass mc in list) 
     { 
      if (mc.Name == "height") 
       mc.Value = 30; 
     } 

I tego zapytania LINQ (przy użyciu wyrażeń lambda), ale to nie jest taka sama jak w górnej pętli foreach, tylko zwraca 1 produkt (jeden rząd) z listy!

Co chcę jest, że zwraca wszystkie elementy (wszystkie wiersze), a tylko chnages odpowiedni jeden (towary określone w WHERE metodzie (-ach) przedłużeniu

list = list.Where(w => w.Name == "height").Select(s => { s.Value = 30; return s; }).ToList(); 

. UWAGA: te 2 Przykład to nie to samo! Powtarzam, linq zwraca tylko 1 pozycję (jeden wiersz), a to jest coś, czego nie chcę, potrzebuję również wszystkich elementów z listy (jak pętla foreach, tylko zmiany, ale nie usuń dowolną pozycję)

+5

* Dlaczego * czy chcesz używać wyrażeń lambda? Kod 'foreach' działa dobrze i jest prosty. LINQ służy do * wyszukiwania danych * bez mutowania. –

+1

Gdzie, z definicji, zwraca tylko pasujące rekordy. Zasadniczo: to nie jest to, czego chcesz - po prostu użyj foreach –

+0

Cześć Jon, znam pętlę foreach, jeśli to ciasto i szybciej, ale chciałbym się nauczyć, to wszystko. Dla niektórych "małych" kodów będzie dobrze. Ale chodzi głównie o to, żeby się uczyć. –

Odpowiedz

64

Możesz użyć ForEach, ale najpierw musisz przekonwertować IEnumerable<T> na List<T>.

list.Where(w => w.Name == "height").ToList().ForEach(s => s.Value = 30); 
+0

Spowoduje to utworzenie nowej listy. Porusza przedmioty, w których Nazwa! = "Wysokość" – Tilak

+0

Tworzy nową listę - I zwraca tylko elementy oparte na klauzuli WHERE. Nie przykład, którego chcę. –

+0

@MitjaBonca moje złe, źle zrozumiałem twoje pytanie. Zobacz moją edycję powyżej. – McGarnagle

2

Można użyć projekcji z lambda oświadczenie, ale oryginalny foreach pętla jest bardziej czytelny i edytuje listę w miejscu zamiast tworzyć nową listę.

var result = list.Select(i => 
    { 
     if (i.Name == "height") i.Value = 30; 
     return i; 
    }).ToList(); 

metodę rozszerzenia

public static void SetHeights(this IEnumerable<MyClass> source, int value) 
{ 
    foreach (var item in source) 
    { 
     if (item.Name == "height") 
     { 
      item.Value = value; 
     } 

     yield return item; 
    } 
} 

var result = list.SetHeights(30).ToList(); 
+0

Czy można tego uniknąć, jeśli blokuje? Być może zdefiniować metodę Select extension? –

+0

Tak, można zdefiniować niestandardową metodę rozszerzenia, ale oryginalne wskazówki są mniej niejasne i łatwiejsze w utrzymaniu i nie utworzą nowej listy, która może być kosztowna. – devdigital

+0

Wiem, jak zrobić metodę extussion cusom, zastanawiałem się tylko, czy można to zrobić w "krótki" sposób, w odniesieniu do kodu ?! Jak pokazał przykład @Robin, tylko że jego kod nie działa! –

-2

można zrobić coś takiego:

var newList = list.Where(w => w.Name == "height") 
       .Select(s => new {s.Name, s.Value= 30 }).ToList(); 

Ale wolałbym wybrać używać foreach ponieważ LINQ jest dla zapytań podczas chcesz edytuj dane.

+0

Z tego też byłam wcześniejsza, ale mam wyjątek: "Nieprawidłowy anonimowy deklarator typu typu, członkowie anonimowi muszą być zadeklarowani z przypisaniem członka, prostym imieniem lub dostępem do członka.". Jest to dla "s.Value = 30". –

+0

Nie przykład, którego chcę, nawet jeśli nie działa. –

8

pewnie bym iść z tym (nie znam jej czystej LINQ), zachować odniesienie do oryginalnej listy, jeśli chce się zachować wszystkie elementy, a powinieneś znaleźć zaktualizowane wartości są tam:

foreach (var mc in list.Where(x => x.Name == "height")) 
    mc.Value = 30; 
1

Co powiecie na: list.Find(x => x.Name == "height").Value = 20; To działa dobrze. Znam jego stary post, ale zastanawiałem się, dlaczego nikt tego nie zasugerował? Czy ten kod ma wadę?

+0

if 'list.Find (x => x.Name ==" height ")' to nic nie zwraca, błąd jest uzyskiwany '[NullReferenceException: Odwołanie do obiektu nie jest ustawione na wystąpienie obiektu.]' –

+0

Zawsze można podać wartość zerową sprawdź przed faktyczną modyfikacją wartości. –

Powiązane problemy