Schnellere Möglichkeit durch eine Liste zu gehen

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von xored.

    Schnellere Möglichkeit durch eine Liste zu gehen

    Hallo zusammen, ich habe ein kleines Performance-Problem.

    Ich habe eine Excel-Spalte mit 31.000 Einträgen (1 Wort pro Zeile).
    Diese sieht so aus:



    Mein Vorhaben ist es, diese in richtige Artikelnummern umzuwandeln. Jede Q-Nummer, hat eine dazugehörige Artikelnummer.
    Dafür habe ich ein DataGridView genommen:



    Das sind natürlich nicht alle, es geht hier um 31.000 Einträge.
    Nun möchte ich aus der EingabeListe, alles in die zugehörige Artikelnummer umwandeln.

    Mein Problem: Mein Programm läuft schon seit ungelogen mehr als 48h... Man sieht, dass er arbeitet, aber ich frage mich, ob es diese Woche noch fertig sein wird.

    Ich habe 2 Möglichkeiten probiert, eine mit DGV, eine mit RTB. Zweitere Methode spart zwar einige % CPU-Auslastung und RAM ein, aber fertig ist auch die Methode noch nicht nach 48h.

    Methode 1:

    VB.NET-Quellcode

    1. Option Strict On
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. For i As Integer = 0 To rtbInput.Lines.Length - 1
    4. If Not String.IsNullOrEmpty((rtbInput.Lines(i))) Then
    5. Dim rowIndex As Integer = -1
    6. Dim tempAllowUserToAddRows As Boolean = DataGridView1.AllowUserToAddRows
    7. DataGridView1.AllowUserToAddRows = False
    8. Dim row As DataGridViewRow = DataGridView1.Rows.Cast(Of DataGridViewRow)().Where(Function(r) r.Cells("ordernumber").Value.ToString().Equals(rtbInput.Lines(i))).First()
    9. rowIndex = row.Index
    10. DataGridView1.Rows(rowIndex).Selected = True
    11. DataGridView1.AllowUserToAddRows = tempAllowUserToAddRows
    12. DataGridView1.CurrentCell = DataGridView1.Rows(rowIndex).Cells(0)
    13. rtbOutput.Text = rtbOutput.Text & vbNewLine & DataGridView1.Rows(rowIndex).Cells(1).Value.ToString
    14. End If
    15. Next
    16. End Sub


    Methode 2:



    VB.NET-Quellcode

    1. Option Strict On
    2. Dim AusgabeListe As New List(Of String)
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. For i As Integer = 0 To rtbInput.Lines.Length - 1
    5. If Not String.IsNullOrEmpty((rtbInput.Lines(i))) Then
    6. For i2 As Integer = 0 To rtbVergleich.Lines.Count - 1
    7. If rtbVergleich.Lines(i2).Contains(rtbInput.Lines(i)) Then
    8. AusgabeListe.Add(GetBetween(rtbVergleich.Lines(i2), "[2]", "[/2]"))
    9. Label3.Text = AusgabeListe.Count.ToString
    10. Else
    11. AusgabeListe.Add("")
    12. Label3.Text = AusgabeListe.Count.ToString
    13. End If
    14. Next
    15. Label3.Text = AusgabeListe.Count.ToString
    16. End If
    17. Next
    18. For Each str As String In AusgabeListe
    19. rtbOutput.AppendText(Environment.NewLine & str)
    20. Next
    21. End Sub


    Wahrscheinlich sind beide Methoden Müll, aber mir fällt gerade nichts anderes ein.. Gibt es was schnelleres? 48h+ sind halt schon hart für 31.000 Zeilen.

    Danke euch! :)
    Grüße,
    xored


    Meine Website:
    www.renebischof.de

    Meine erste App (Android):
    PartyPalooza
    @xored Pack die Daten mal sowohl aus dem DGV als auch aus der RTB in eine Liste oder ein Array, Array ist schneller als List(Of T). Eliminiere da gleich die Leerzeilen.
    Das Befüllen der Label kannst Du weglassen, der Text wird nicht upgedatet.
    Zu Test-Zwecken kannst Du ja eine Console-Ausgabe einbauen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dictionary<TKey,TValue> Klasse

    Bau dir zuerst ein Dictionary mit den Zuordnungen zusammen. Dieses ist genau dafür da, dass du einen schnellen Lookup hast. Hier mal ein Pseudocode, ich kann kein VB mehr:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim dictionary As New Dictionary(Of String, String)
    3. For i As Integer = 0 To rtbVergleich.Lines.Count - 1
    4. dictionary.Add(GetBetween(rtbVergleich.Lines(i), "[1]", "[/1]"), GetBetween(rtbVergleich.Lines(i), "[2]", "[/2]"))
    5. Next
    6. For i As Integer = 0 To rtbInput.Lines.Length - 1
    7. If Not String.IsNullOrEmpty(rtbInput.Lines(i)) Then
    8. Dim result As String = Nothing
    9. If dictionary.TryGetValue(rtbInput.Lines(i), result) Then
    10. AusgabeListe.Add(result)
    11. Else
    12. AusgabeListe.Add("")
    13. End If
    14. End If
    15. Next
    16. Label3.Text = AusgabeListe.Count.ToString
    17. rtbOutput.Text = String.Join(Environment.NewLine, AusgabeListe)
    18. End Sub

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

    Danke euch beiden, habe mich für die Methode von @RodFromGermany entschieden, da ich die Antwort zuerst gelesen habe.
    Es klappt nun, die Liste ist in wenigen Sekunden abgearbeitet. Danke!! :)

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Imports System.Runtime.CompilerServices
    4. Module ArrayExtension
    5. <Extension()>
    6. Public Sub Add(Of T)(ByRef arr As T(), item As T)
    7. If arr IsNot Nothing Then
    8. Array.Resize(arr, arr.Length + 1)
    9. arr(arr.Length - 1) = item
    10. Else
    11. ReDim arr(0)
    12. arr(0) = item
    13. End If
    14. End Sub
    15. End Module
    16. Module Module1
    17. Dim EingabeListe() As String
    18. Dim VergleichsListe() As String
    19. Dim AusgabeListe() As String
    20. Public Function GetBetween(ByVal Source As String, ByVal Del1 As String, ByVal Del2 As String) As String
    21. Dim nIndexStart As Integer = Source.IndexOf(Del1)
    22. Dim nIndexEnd As Integer = Source.IndexOf(Del2)
    23. If nIndexStart > -1 AndAlso nIndexEnd > -1 Then
    24. Dim res As String = Strings.Mid(Source, nIndexStart + Del1.Length + 1, nIndexEnd - nIndexStart - Del1.Length)
    25. Return res
    26. Else
    27. End If
    28. End Function
    29. Sub Main()
    30. For Each LineEingabe As String In File.ReadLines(My.Computer.FileSystem.CurrentDirectory & "\EingabeListe.txt")
    31. EingabeListe.Add(LineEingabe)
    32. Next
    33. For Each LineVergleich As String In File.ReadLines(My.Computer.FileSystem.CurrentDirectory & "\VergleichsListe.txt")
    34. VergleichsListe.Add(LineVergleich)
    35. Next
    36. For Each EingabeValue As String In EingabeListe
    37. For Each VergleichsValue As String In VergleichsListe
    38. If VergleichsValue.Contains("[1]" & EingabeValue & "[/1]") Then
    39. AusgabeListe.Add(GetBetween(VergleichsValue, "[2]", "[/2]"))
    40. ' Console.WriteLine("Added " & GetBetween(VergleichsValue, "[2]", "[/2]") & " ItemNumber: " & AusgabeListe.Count.ToString)
    41. End If
    42. Next
    43. Next
    44. Console.WriteLine("Added " & AusgabeListe.Count.ToString & " items to the list")
    45. System.IO.File.WriteAllLines(My.Computer.FileSystem.CurrentDirectory & "\Konvertiert.txt", AusgabeListe)
    46. Console.ReadLine()
    47. End Sub
    48. End Module


    Meine Website:
    www.renebischof.de

    Meine erste App (Android):
    PartyPalooza
    @xored Deine ArrayExtension halte ich für suboptimal.
    Pack alle Deine Daten in eine List(Of T) und konvertiere die hinterher ggf. mit .ToArray().
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!