Znalezienie indeksu listy przy pomocy Linq

0

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.

0

A po co ci sam indeks w liście? Cały obiekt możesz wyciągnąć za pomocą .Where().

0

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ę.

3

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.

1

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...

0

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>
0

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.

0
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.

1

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

0

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.

0

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:"

0
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#?

0

Przeczytaj temat jeszcze raz, bo chyba nie odnosisz się do moich postów.

  1. 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.
  2. "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.
  3. "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.

1

Na tym zakończmy ten flejm, proszę. Proponuję nie pisać dalszych postów, przynajmniej do czasu odpowiedzi autora wątku.

0
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.

0

LINQ i ogólnie IEnumerable są tak skonstruowane, że indeks elementu jest nieistotny. Kod można tak przekształcić, że nie jest to potrzebne.

0 użytkowników online, w tym zalogowanych: 0, gości: 0