Mam listę zawierającą obiekty klasy. Klasa ta posiada kilka własności, gdzie jedną z nich jest (long) numer aukcji.
Chodzi teraz o to, aby znaleźć indeks tego obiektu kiedy numer aukcji jest równy parametrowi. (nie wydaje mi się, aby mogły się powtarzać).
Słabo znam lambdy i linq ,dlatego będę wdzięczny za wszelkie propozycje.
Pozdrawiam.
A po co ci sam indeks w liście? Cały obiekt możesz wyciągnąć za pomocą .Where()
.
Wszystkie licytowane przedmioty trzymam w liście obiektów klasy która ma własności nazwy, indeksu aukcji itd. Aby zalicytować w allegrowebapi potrzebuje indeks tej aukcji. Domyślnie będę chciał licytować zaznaczony item na listboxie czy czymś innym ,a więc potrzebuję indeks obiektu w tej liście. Chyba ,że głupio kombinuję.
Jeżeli nie doprowadzisz do desychronizacji pomiędzy swoją listą a listboxem to wystarczy lista[listbox.selectedindex]
. Ewentualnie w listboxie możesz trzymać całe obiekty, ale raczej tego nie polecam.
Można to zrobić w LINQ, ale po co?...
static void Main( string[] args )
{
List<Osoba> lista = new List<Osoba>();
lista.Add(new Osoba("Janek"));
lista.Add(new Osoba("Mietek"));
lista.Add(new Osoba("Jozek"));
lista.Add(new Osoba("Kasia"));
Console.WriteLine( FindIndex(lista, "Jozek"));
Console.WriteLine( FindIndexLinq(lista, "Jozek"));
Console.ReadLine();
}
public static int FindIndex(List<Osoba> lista, string szukaneImie )
{
for(int i = 0; i < lista.Count; i++)
if ( lista[i].Imie == szukaneImie )
return i;
throw new Exception("Not found");
}
public static int FindIndexLinq( List<Osoba> lista, string szukaneImie )
{
var find = lista.Select(( osoba, index ) => new { Osoba = osoba, Index = index })
.Where(a => a.Osoba.Imie == szukaneImie);
if(find.Any())
return find.First().Index;
else
throw new Exception("Not found");
}
public class Osoba
{
public string Imie;
public Osoba( string imie )
{
this.Imie = imie;
}
}
... kod w LINQ w tym przypadku jest mniej czytelny, no chyba że można ładniej, dzisiaj mam zaćmienie...
Linq dłuższe od ręcznie napisanej pętli? chyba żartujesz:
public static int FindIndexLinq(List<Person> personList, string nameToFind)
{
return personList.Select((osoba, person) => new { Person = person, Index = index }).First(a => a.Person.Name == nameToFind).Index;
}
albo jeszcze prościej
public static int FindIndexLinq(List<Person> personList, string nameToFind)
{
return personList.FindIndex(p => p.Name == nameToFind);
}
<strike>drugi kawałek kodu też da się napisać lepiej, acz nie pamiętam, czy dla stringa obowiązuje tutaj zasada porównywania po wartości, czy po referencji:
public static int FindIndex(List<Person> personList, string nameToFind) { return personList.IndexOf(nameToFind); }
</strike>
Czyli tak właściwie poprawiłeś kod LINQ na to co ja dałem, czyli kod który jest mniej czytelny od tradycyjnego for. Z FindIndex nie korzystałem, ponieważ to nie jest dostępne w IList.
Zenek1999 napisał(a):
Czyli tak właściwie poprawiłeś kod LINQ na to co ja dałem, czyli kod który jest mniej czytelny od tradycyjnego for. Z FindIndex nie korzystałem, ponieważ to nie jest dostępne w IList.
Weź koleś nie ort! się z modem i wracaj do książek. Masz tylko 12 postów i twój kod jest do d*py.
public static int FindIndexLinq(List<Person> personList, string nameToFind)
{
return personList.FindIndex(p => p.Name == nameToFind);
}
Najlepszy kod.
ciężko inaczej napisać sam warunek. reszta ma pewną - nazwijmy ją subtelną - różnicę. a zdanie "z FindIndex nie korzystałem, ponieważ to nie jest dostępne w IList" to chyba żarcik? dodam jeszcze, że o ile czasem z przejrzystością kodu w linq bywa różnie, o tyle niesamowicie przyspiesza pisanie, a zatem zmniejsza koszt pracy programisty. pewnie jesteś na etapie "wydajność kur*a!!!1", ale kiedyś zauważysz, że ta wydajność to nie szybkość kodu za wszelką cenę. - ŁF 9 minut temu
... serio?
Na forum staram się pomagać początkujący i odpowiadać na zadane pytania dając czytelny przykład. Napisałem krótki program który korzysta z List<T>, ale pytanie brzmi "Znalezienie indeksu listy przy pomocy Linq", nie "Znlezienie indeksu System.Collection.Generic.List", FindIndex nie jest częścią LINQ a implementacji powyższej klasy. Skorzystanie z LINQ w tym zadaniu jest gorsze, bo:
- jest mniej czytelne
- jest dłuższe
- jest mniej wydajne
- jest bardziej skomplikowane
O ile pierwszy argument jest subiektywny, o tyle pozostałe są obiektywne. Jak stworzysz metodę która działa jak FindIndex z List<T>? Jeśli użyjemy for...
for(int i = 0; i < lista.Count; i++)
if ( lista[i].Imie == szukaneImie )
return i;
return -1;
Korzystając z LINQ na siłę...
return lista.Select(( osoba, index ) => new { Osoba = osoba, Index = index })
.Where(a => a.Osoba.Imie == szukaneImie)
.Select(a => a.Index + 1)
.FirstOrDefault() - 1;
Czyli widać, że sam kod jest dłuższy, mniej wydajny i bardziej skomplikowany. Ostatnio był na forum temat o "ułatwianiu sobie życia" korzystając z dobrodziejstw typu typy anonimowe, operator lambda itd. Jednak próba rozwiązania zadanego problemu przy pomocy LINQ jest niepotrzebnym utrudnianiem pracy, chyba na zasadzie "tylko lamusy korzystają z for". ;)
stworzyłeś potworka...
var result = lista.Select((osoba, index) => new { Osoba = osoba, Index = index }).FirstOrDefault(a => a.Osoba.Imie == szukaneImie);
return result != null ? result.Index : -1;
zgadzam się, istnieje multum przykładów, gdzie linq będzie mniej czytelne i prawie zawsze linq będzie wolniejsze. ale linq daje Ci coś, co to wszystko wynagradza - generyczne narzędzie, którym większość pętli zapiszesz w jednej linijce, redukując ilość kodu, pozwalając na robienie takich samych zapytań do xml, bazy danych, list, tablic, itp. itd. akurat w tym przykładzie wymaga to więcej kodu, jednak zwykle tak nie jest.
optymalizacja szybkości działania kodu to nieco inna bajka. znajdujesz zwykle nieliczne wąskie gardła i to tam przyspieszasz kod/algorytm do upadłego (często "do upadłego" trwa pięć minut i sprowadza się do dodania indeksów w bazie ;-)). reszta kodu ma nie działać wolno, ale nikt nie oczekuje, żeby np. po kliknięciu na przycisk okno dialogowe otworzyło się w 3ms, a nie 10 czy 30. w przypadku aplikacji webowych taniej jest dokupić serwer, niż inwestować pieniądze w czas programistów, w którym zamiast zarabiać pieniądze dla firmy profilują i optymalizują aplikację. kasa, to jest to co się liczy, a nie wyczesany kod w każdym miejscu.
Napisałem krótki program który korzysta z List<T>, ale pytanie brzmi "Znalezienie indeksu listy przy pomocy Linq", nie "Znlezienie indeksu System.Collection.Generic.List", FindIndex nie jest częścią LINQ a implementacji powyższej klasy.
jak już mnie pouczasz to zważ, że - parafrazując - pytanie brzmi "Znalezienie indeksu listy przy pomocy Linq", a nie "Znalezienie indeksu przy pomocy pętli for". a skoro sam się nie trzymasz pytania, to nie wytykaj i mi, że podałem coś szybszego i znacznie prostszego od Twojej pętelki.
jak już mnie pouczasz to zważ, że - parafrazując - pytanie brzmi "Znalezienie indeksu listy przy pomocy Linq", a nie "Znalezienie indeksu przy pomocy pętli for". a skoro sam się nie trzymasz pytania, to nie wytykaj i mi, że podałem coś szybszego i znacznie prostszego od Twojej pętelki.
Chyba coś Ci się pomyliło, bo w moim pierwszym poście podałem rozwiązanie problemu za pomocą LINQ i ekwiwalent w for, tak żeby osoba ucząca się miała porównanie LINQ do czegoś dobrze znanego. Ty napisałeś swój post, ponieważ "Linq dłuższe od ręcznie napisanej pętli? chyba żartujesz:" i napisałeś jedną linię kodu która była błędna, potem dopisałeś drugą która korzysta z anonimowego typu i teraz trzecią która w końcu dała tę samą funkcjonalność co ja dałem w pierwszym poście, tylko patrząc na kod z Twojego ostatniego postu...
"Linq dłuższe od ręcznie napisanej pętli? chyba żartujesz:"
Zenek1999 napisał(a):
Chyba coś Ci się pomyliło, bo w moim pierwszym poście podałem rozwiązanie problemu za pomocą LINQ i ekwiwalent w for
po czym jedziesz po mnie, kiedy również podałem jedną linijkę linq i alternytwne, szybsze i najbardziej przejrzyste rozwiązanie używające gotowej metody, które to odrzuciłeś, bo (sic!) IList, o którym nikt wcześniej nie wspominał, nie specyfikuje jej. zresztą tu się mylisz, bo generyczne IList zawiera definicję takiej metody.
Zenek1999 napisał(a):
napisałeś jedną linię kodu która była błędna, potem dopisałeś drugą która korzysta z anonimowego typu i teraz trzecią która w końcu dała tę samą funkcjonalność co ja dałem w pierwszym poście, tylko patrząc na kod z Twojego ostatniego postu...
a co to ma do rzeczy?
Zenek1999 napisał(a):
"Linq dłuższe od ręcznie napisanej pętli? chyba żartujesz:"
tylko tutaj nie mogę się z Tobą nie zgodzić. w tym konkretnym przypadku for jest krótszy o kilka znaczków - tylko przez dość długie obejście problemu pobrania indeksu. z mojego kilkuletniego doświadczenia w pracy z linq wynika, że zwykle znacznie zmniejsza ilość kodu. ale być może pracuję z specyficznymi rozwiązaniami...
tak dla zaspokojenia mojej próżnej ciekawości - ile lat pracujesz jako programista, w tym ile z c#?
Przeczytaj temat jeszcze raz, bo chyba nie odnosisz się do moich postów.
- Nigdzie nie "jechałem po Tobie".
2 Rozwiązania nie "odrzuciłem", a tylko zauważyłem że IList nie implementuje FindIndex, co jest zgodne z tym co podaje MSDN, chyba że mówimy o innych interfejsach. Pewnie pomyliło Ci się z IndexOf. - "a co to ma do rzeczy?", to chyba był powód dla którego napisałeś pierwszego posta, a przynajmniej takie można odnieść wrażenie.
- "tak dla zaspokojenia mojej próżnej ciekawości - ile lat pracujesz jako programista, w tym ile z c#?" - nie odpowiem Ci na to pytanie. Od początku robisz personalne wycieczki i niedokładnie czytasz.
Jestem na tym forum żeby pomagać i się uczyć, a Ty najwyraźniej szukasz zwady.
Na tym zakończmy ten flejm, proszę. Proponuję nie pisać dalszych postów, przynajmniej do czasu odpowiedzi autora wątku.
Zenek1999 napisał(a):
pytanie brzmi "Znalezienie indeksu listy przy pomocy Linq", nie "Znlezienie indeksu System.Collection.Generic.List", FindIndex nie jest częścią LINQ a implementacji powyższej klasy. Skorzystanie z LINQ w tym zadaniu jest gorsze, bo:
- jest mniej czytelne
- jest dłuższe
- jest mniej wydajne
- jest bardziej skomplikowane
Nic dodać, nic ująć. W tym przypadku użycie LINQ jest przerostem formy nad treścią. I chyba sam pomysł przetwarzania kolekcji przez LINQ z pamiętaniem kontekstu (w tym wypadku indeksu) jest słaby.
LINQ i ogólnie IEnumerable
są tak skonstruowane, że indeks elementu jest nieistotny. Kod można tak przekształcić, że nie jest to potrzebne.