Indexsuche in einer List(Of Structure)

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Takafusa.

    Indexsuche in einer List(Of Structure)

    Hallo,

    Ich hatte früher eine List(Of String), da konnte ich bequem den Index mit Liste.IndexOf("Element") suchen, wenn ich einen String gegeben hatte.

    Nun hab ich aber eine List(Of [Eine Struktur]), wo der gegebene String ein Mitglied einer Struktur und keine eigene Liste ist.

    Jetzt zu meiner Frage:

    Kann ich, ohne eine zeitaufwendige For-, oder For-Each-Schleife zu verwenden, mit der neuen Liste auch den Index des Struktur-Elements bestimmen, wenn ich einen String gegeben habe, der ein Member der Struktur ist? ?(

    Ich will das ganze zum Aufrufen einer Prozedur verwenden, die alle Einträge der Struktur am jeweiligen Index in Textboxen anzeigt, wenn es einen Teil der Struktur gegeben hat.

    Mein bisheriger Code für das Anzeigen der Struktur(mit For-Each-Schleife):


    VB.NET-Quellcode

    1. For Each u In StrukturListe
    2. If u.Titel = GegebenerString Then
    3. ZeigeStrukturAn(StrukturListe.IndexOf(u))
    4. End If
    5. Next


    Mein früherer (einzeiliger) Code zum Anzeigen der List(Of String):

    VB.NET-Quellcode

    1. ZeigeStrukturAn(StringListe.IndexOf(GegebenerString))



    Vielleicht nützlicher Hinweis:
    GegebenerString kommt aus dem Text eines TreeNodes und wird dorthin beim Einlesen durch ein Strukturmember namens Index festgelegt

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB_Gamer“ ()

    VB_Gamer schrieb:

    Kann ich, ohne eine zeitaufwendige For-, oder For-Each-Schleife zu verwenden,

    Die "interne" Suche in einer List(of) ist auch nix anderes als ne Schleife. Wenn du was schnelles willst, musst du Sorted...(Of) nehmen oder SortedSet(of) oder HashSet(of). Dann geht das suchen auch entsprechend schneller. Geht natürlich nur dann schnell, wenn das gesuchte Feld auch das ist, nach dem sortiert ist.

    Ansonsten geht ein Einzeiler immer auch mit LINQ:

    VB.NET-Quellcode

    1. Public Class foo
    2. Public s As String
    3. End Class
    4. Public Class bar
    5. Public Sub baz()
    6. Dim l As List(Of foo)
    7. ' Einzeilige suche:
    8. Dim f As foo = From ff As foo In l Where ff.s = "Hello World" Select ff Take 1
    9. End Sub
    10. End Class


    In FW 4 kann man auch "... in l.AsParallel" machen, um die Suche evtl zu beschleunigen.
    Wobei man bei den Erweiterungen für paralleles Rechnen meiner Erfahrung nach auch vorsichtig sein muss, wenn man auf die selben Datenstrukturen zugreift. Dann kann es nämlich genauso gut passieren, dass durch wechselseitig blockierende Semaphore bzw. Monitore die Laufzeit nach oben anstatt nach unten geht...
    Das Problem besteht natürlich nicht erst seit .NET 4, aber früher hat sowas niemand so schnell parallelisiert. ;)

    hal2000 schrieb:

    VB.NET-Quellcode

    1. Dim result = From s In StrukturListe Select s Where s.Titel = "Suchstring"

    Jawoll, das sieht doch recht gut aus, wenn das wirklich geht, ist es perfekt. :D :thumbsup: :D

    Genauso hab ich mir das vorgestellt, aber ich hätte nicht gedacht, das so was geht, weil ich mal nen Thread gelesen hab, der heiß: Gibt es so etwas wie Where, da hat keiner gesagt, dass es es gibt. :|

    Jedenfalls danke, ich teste es dann mal :thumbsup:


    *EDIT: Es funktioniert!
    Aber ich habschon wieder eine Frage. Wie kann man beim Serialize/Deserialize es so einstellen, dass die Datei verschlüsselt ist?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB_Gamer“ ()

    Entschuldigt. Auch wenn dieser Beitrag schon sehr alt ist, passt meine Frage eigentlich nur dazu.

    Ich stehe vor dem selben Problem und diese Lösung hier schein mit dem Einzeiler genau mein Ding zu sein.

    Nun verstehe ich leider nicht ganz die Variable "result".
    Wie bekomme ich daraus den Indexwert des Arrays (bzw. der Struktur) im Format von Long oder Integer?

    Danke und entschuldigt die Threadaufwärmung.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Das ist halt Linq, und da wird nur mit Objekten gearbeitet, nicht mit Indizes. Du kannst aber ein bisschen tricksen, dann geht das schon:

    VB.NET-Quellcode

    1. Dim list = New List(Of TestStruct)
    2. Dim s As String = "der String"
    3. Dim index = list.Select(Function(item, i) New With {.Index = i, .Item = item}).FirstOrDefault(Function(p) p.Item.Value = s).Index
    Bitte beachte, dass ein Fehler geworfen wird, wenn das Element nicht enhalten ist, anstatt dass -1 zurückgegeben wird, da hier eben alles auf Objekten und nicht auf Indizes basiert.
    Wahrscheinlich bist du aber mit ner einfachen Schleife sowieso besser aufgehoben:

    VB.NET-Quellcode

    1. Dim list = New List(Of TestStruct)
    2. Dim s As String = "der String"
    3. Dim index = -1
    4. For i = 0 To list.Count - 1
    5. If list(i).Value = s Then
    6. index = i
    7. Exit For
    8. End If
    9. Next
    Danke für die Antwort.

    Schleife habe ich auch schon überlegt.
    Das geht Geschwindigkeitsmäßig zwar bei 200-300 Einträgen, aber bei 2000 bis 10000 Einträgen wird das schon etwas zäh.
    Besonders wenn dann die Anwendung noch auf einem PocketPC auch läuft - da fehlt die Leistung.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Danke Leute.
    Ich habe die Rechenleistung und die Schleife doch unterschätzt.
    100000 Elemente werden immer noch unter einer halben Sekunde durchsucht. Das ist mehr als ausreichend.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Sorry, dass ich den Beitrag wieder aufwärme, aber meine Frage schließt eigentlich hier an bzw. behandelt das selbe Thema.

    Ausgangspunkt ist eine Structure.
    Hier möchte ich im Wert "Bezeichnung" nach einem Suchbegriff suchen.
    Aber nicht ob dieser exakt übereinstimmt, sondern ob der Suchbegriff im Wert Bezeichnung enthalten ist.
    Das ganze natürlich noch Case Insensitive ;-).

    Also den gewünschten Index in der Structure nach exakter Übereinstummung zu suchen funktioniert ja:

    VB.NET-Quellcode

    1. <Serializable()>
    2. Structure FotoListe_struct
    3. Dim InterneID As String
    4. Dim Bezeichnung As String
    5. Dim Erstellungsdatum As String
    6. Dim Info As String
    7. Dim DateiName As String
    8. Dim Verknuepfungen As String
    9. End Structure
    10. Public MaxFotoListe As Integer = 10000
    11. Public Fotoliste(MaxFotoListe) As FotoListe_struct
    12. EintragIndex = Array.FindIndex(Fotoliste, Function(f) f.Bezeichnung = Suchbegriff)


    Aber eigentlich möchte ich sowas in der Art:

    VB.NET-Quellcode

    1. EintragIndex = Array.FindIndex(Fotoliste, Function(f) f.Bezeichnung.ToUpper.Contains(Suchbegriff.ToUpper))


    Aber irgendwie bin ich zu wenig schlau um zu verstehen wie (und ob) das geht.
    Ich würde halt ungern per For-Next Schleife die 10000 Einträge durchgehen wollen (dauert ja viel zu lange).

    Habt Ihr da für mich einen Tipp?

    LG Roland
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Ich wüsste was mit einer anonymen Methode, aber da müsstest du was ändern.
    Du hast einen Array, Länge 10000, davon sind sehr viele indicies nicht belegt, ich wüsste mit einer anonymen Methode grad nicht wie man ein nicht nullable-object auf nothing prüfen kann, vllt. auch ein denkfehler meinerseits. Daher müsstest du da eine List(of T) nehmen, dann kannste so recht einfach, alle Structuren wo das zu suchende in der Bezeichnung drin ist finden und ausgeben.
    Ob du nun einen Array oder List(of T) für die gefundendenen Elemente nimmmst, ist egal.

    VB.NET-Quellcode

    1. Dim structs As List(Of FotoListe_struct) = (From struct In Fotoliste Where struct.Bezeichnung.ToUpper().Contains("Suchwort".ToUpper()) Select struct).ToList()
    2. Debug.WriteLine(structs.Count.ToString)


    Das wäre meine Idee, aber evtl. weis jemsnd wie man das mit den nicht-nullables und einer anonymen Methode machen kann, dann kannste beim Arary bleiben.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Takafusa“ ()

    Vielen Dank.
    Ich habe meine Fehler schon gefunden.

    VB.NET-Quellcode

    1. EintragIndex = Array.FindIndex(Fotoliste, Function(f) f.Bezeichnung.ToUpper.Contains(Suchbegriff.ToUpper))

    Obiger Code funktioniert schon, nur war nicht in jedem Feld "Bezeichnung" ein Wert drin, sondern auch "Nothing" ;-).

    Aber dennoch ist Dein Code genau das was ich gesucht habe.

    Vielen Dank @Takafusa,

    Du hast den Knoten bei mir gelöst und jetzt verstehe ich dieses List Of Gedöns schon ein wenig mehr. Habe mich bisher nicht wirklich damit beschäftigt.

    Dein Code funktioniert einwandfrei. Eine Zeile zum Suchen verschiedener Felder in einer Struct, ähnlich wie SQL. Ich bin begeistert.

    VB.NET-Quellcode

    1. Dim structs As List(Of FotoListe_struct) = (From struct In Fotoliste Where struct.Bezeichnung.ToUpper().Contains(Suchbegriff.ToUpper()) Or struct.Info.ToUpper().Contains(Suchbegriff.ToUpper()) Select struct).ToList()
    2. 'Hier alle gefundenen Dateinamen hinzufügen
    3. For i As Integer = 0 To structs.Count - 1
    4. FotosInOrdner(MaxFotosInFolder) = Path.Combine(Projekte(My.Settings.ZuletztVerwendetesProjekt).Datenpfad, "Fotos", structs(i).DateiName)
    5. MaxFotosInFolder += 1
    6. Next i


    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „dive26“ ()

    Ja das dachte ich mir, wollte erst alles durchlaufen und die indicies sammeln, wo die Bedingun zutrifft, aber so fand ich das besser und es ist auch kürzer. Auch ist mit List(of T) einfacher umzugehen als mit Arrays.

    dive26 schrieb:

    Du hast den Knoten bei mir gelöst und jetzt verstehe ich dieses List Of Gedöns schon ein wenig mehr.


    Also List(of Gedöns), xD, ist ähnlich wie ein Array, nur das die größe dynamisch ist, man auch weitere Sachen hat wie Add, Remove, AddRAnge, RemoveRange und noch mehr all das bietet ein Array nicht, auch die fixe Größe beim array, wie auch hier mit "leeren indices" hat mir oft schon Probleme bereitet. Sobald eine Fixe Größe vorliegt z.B. bei 2D Spielfeldern, wo alles im Array nicht nothing ist, da nehm ich auch Arrays(mehrdimensional), ich mach grad eine Tetris Variante auch da nehm ich nen 2D Array, sonst aus Bequemlichkeit List(of Gedöns).

    Ich täte dir auf jeden Fall empfehlen mehr damit zu machen, dann kommt das Verständniss dafür, nach der Zeit wie von allein. Lass dich dabei nicht von den anonymen Methoden die du hier im Forum in zusammenhang mit List(of T) liest in die Irre führen. Da sind die anonymen Methoden das komplizierte wenn man sich damit nicht auskennt, nicht die List(of T). Auch ist es mehr arbeit, die Anzahl zu ermitteln im Array, Array.Legnth haut ja die ganze Länge raus, auch wenn 50% NIX ist, da ist die dynamische Größe der List(of T) wieder von Vorteil.(list.count)

    Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von „Takafusa“ ()