Gleiche Kombinationen in Dictionary finden

  • VB.NET

Es gibt 34 Antworten in diesem Thema. Der letzte Beitrag () ist von exc-jdbi.

    Gleiche Kombinationen in Dictionary finden

    Hallo zusammen,

    ich habe ein Dictionary(Of String, Integer)
    Der Key ist immer 10-stellig und eine Kombination aus Buchstaben von a bis z (Jeder Buchstabe kann pro Key jeweils nur einmal vorkommen.
    Der Wert ist ein Integer und soll angehoben werden, wenn eine Kombination mehrfach vorkommt. Beim ersten mal 1, beim zweiten mal 2, usw...

    Zu zählen wie oft der gesamte Key in meiner Liste vorkommt habe ich schon hinbekommen.

    Ich würde nun gern aber auch ermitteln können, wie oft eine 2,3,4,5,6,7,8,9- stellige Kombination in dem 10-stelligen Key vorkommt. Also hier mal ein Beispiel:

    Key 1:"zgkgjabcdp"
    Key 2:"uiaobecqdm"

    In beiden Keys kommen die Buchstaben "abcd" vor. Die Reihenfolge soll hier keine Rolle spielen.

    Ich hoffe das ist halbwegs verständlich erklärt.
    Bis jetzt habe ich leider nichtmal einen Ansatz wie ich das hinbekommen soll. Wie die Werte gespeichert sind ist auch egal, kann meinetwegen eine Tabelle sein. Das mit dem Dictionary ist nur das Biespiel mit dem ich die erste Hürde genommen habe.

    Viele Grüße
    nicerdicer
    Hallo @nicerdicer

    Ich finde es immer so amüsant. Da stellt man Aufgabenstellungen, die in dem Sinne noch gar nicht ausgereift sind, und zeigt im Voraus noch keine Zeile Code. Mich würde z.B. interessieren, wie hast du den ersten Part gelöst?

    Weil ich mutmasse mal, dass das nicht mit einer Dictionary(Of String, Integer) gelöst worden ist. Weil Dictionary im Normalfall einen Fehler ausgeben würde, wenn versucht wird zwei gleiche Keys mit zwei unterschiedlichen Values rein zu Adden. Ich vermute also das Hochzählen des Values ist mit einem anderen Werkzeug gemacht worden.

    Zum zweiten Teil, kann mit der Extention GroupBy herausgefunden werden, welche Buchstaben im Key vorhanden sind. Eventuell muss es sogar aus dem Dictionary herausgelöst werden.

    Der Vergleich ist nun eigentlich ziemlich einfach, dass könnte wahrscheinlich sogar mit einer ganz einfachen LINQ gelöst werden. Aber dazu würde ich vorschlagen, du zeigst einfach mal was du schon hast, oder ein vergleichbares Beispiel, und dann sollte es viel einfacher sein, eine mehr oder weniger gute Lösung zu erarbeiten.


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „exc-jdbi“ ()

    ich würde auch wie von @exc-jdbi vorgeschlagen Linq verwenden.

    zunächst die Keys auslesen und Count verwenden

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. Dim InputString As String = "zgkgjabcdp"
    3. Dim CharGroup = _
    4. ( _
    5. From c In InputString.ToCharArray() _
    6. Group c By c Into Group _
    7. Select New With {.buchstabe = c, .vorkommen = Group.Count}).ToList _
    8. .OrderBy(Function(x) x.buchstabe)
    9. For Each item In CharGroup
    10. Debug.WriteLine("Anzahl von [{0}]: {1}", item.buchstabe, item.vorkommen)
    11. Next
    12. End Sub

    Hallo @exc-jdbi

    Die Daten kommen nicht von einem Dictionary, ich löse das aber über eines.
    Doppelte Keys habe ich nicht.


    VB.NET-Quellcode

    1. Dim valuedict As Dictionary(Of String, Double)
    2. If valuedict Is Nothing Then
    3. valuedict = New Dictionary(Of String, Double)
    4. End If
    5. Dim counter As Integer = 0
    6. If valuedict.ContainsKey(charchain) = False Then
    7. valuedict.Add(charchain, 1)
    8. Else
    9. valuedict(charchain) += 1
    10. End If
    11. counter += 1


    CodeTags korrigiert ~VaporiZed

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

    So funkst das natürlich. :saint:

    VB.NET-Quellcode

    1. valuedict.Keys.Where(Function(str) CheckDictKeys(str, abcd))

    VB.NET-Quellcode

    1. Private Function CheckDictKeys(str As String, str2 As String) As Boolean
    2. Return str2.Where(Function(c) str.Contains(c)).Count = str2.Length
    3. End Function


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „exc-jdbi“ ()

    Vielen Dank für eure beiden Antworten, ich sehe mir das zu Hause noch einmal genauer an.

    So wie ich das verstehe muss ich bei der Lösung von @exc-jdbi einen Zielstring angeben (also gezielt nach einer Zeichenfolge suchen).

    Bei der Lösung von @Kasi kann ich herausfinden, in wie vielen "charstrings" ein gewisser Buchstabe vorkommt.

    Mein Ziel ist es jedoch herauszufinden, welche x-beliebige n-stellige Buchstabenkombination am häufigsten in allen "charstrings" vorkommt, ohne eine nach einer speziellen Zeichenfolge zu suchen.

    Z.B.: Welche 4 Buchstaben kommen in den gesamten "charstrings" am häufigsten zusammen vor?

    Korrigiert mich bitte wenn ich falsch liege.

    Ps: Die Arrays sind beim Vgl. schon sortiert.
    Ach so die sind immer 10 lang, und du willst wissen welche Kombination an Buchstaben am meisten vorkommt. ?

    Zeig uns vielleicht nochmals ein Beispiel bitte.

    Vorschlag, ich weiss aber immer noch nicht ob es das ist was du suchst.

    VB.NET-Quellcode

    1. ​Dim res = Statistik(valuedict.Keys.ToArray)

    VB.NET-Quellcode

    1. Private Function Statistik(str() As String) As String
    2. Dim result = New StringBuilder
    3. Dim alpha = "abcdefghijklmnopqrstuvwxyz"
    4. For Each c In alpha
    5. Dim total = 0
    6. For Each s In str
    7. If s.Contains(c) Then
    8. total += 1
    9. End If
    10. Next
    11. If total = str.Length Then
    12. result.Append(c)
    13. End If
    14. Next
    15. Return result.ToString
    16. End Function

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „exc-jdbi“ ()

    @exc-jdbi @Kasi

    Also genau, die charstrings sind immer 10 Zeichen lang. Und ich möchte aus 100, 1000 charstrings herausfinden, welche Kombination (2er, 3er, 4er, usw...) am häufigsten vorkommt.
    Als Beispiel folgende 5 charstrings (Ich benutze Mal Nummern von 1-100 anstatt von Buchstaben, ist anschaulicher:

    "1,2,3,4,10,20,30,40,50,60"
    "2,3,4,5,11,21,31,41,51,61"
    "3,4,5,6,12,22,32,42,52,62"
    "2,3,4,5,13,23,33,43,53,63"
    "1,2,3,4,14,24,34,44,54,64"

    Hier kommt die unterstrichene 3er-Zahlenkombination "2,3,4" (Reihenfolge egal!) in den 5 Strings am häufigsten vor, also genau 4 mal.
    Als 2-er Zahlenkombination würden die Zahlen "3,4" am häufigsten vorkommen.

    Ich möchte also z.B. fragen "Welche 3er-Zahlenkombination kommt am häufigsten in den 5 Strings vor?". Als Antwort möchte ich bekommen "2,3,4".
    Hoffe das ist jetzt verständlich genug :)
    Ich weiß das ist eine komische Aufgabenstellung, aber für mich Augenblicklich leider mit meinem Wissen und logischen Verständnis unlösbar.
    Das ist immerhin eine denkbare Aufgabenstellung.
    Nun schreib eine Function, die diese Aufgabenstellung zunächstmal nur ausdrückt.
    Also welche Parameter kriegt die und was gibt die zurück?
    Im innern soll die Function noch garnet funktionieren, aber der erste Schritt ist immer, dass man das Problem überhaupt mal in vb-code formuliert.

    Dann schreib eine Test-Methode, die obige Funktion korrekt aufruft - ihr also etwas übergibt, und etwas zurückerhält.

    Mit diesen Vorgaben deinerseits kann man sich dann ans Entwickeln machen - so aus der Tasche zieht das vermutlich niemand.
    Hallo noch einmal,
    ich habe jetzt keine Funktion in dem Sinne verfasst, sondern habe versucht erst einmal alle Zahlenkombinationen jeweils miteinander abzugleichen (Mit Linq.Intersect).
    Damit keine doppelten Abgleichungen stattfinden habe ich jedem Integer Array eine ID gegeben und vor dem Vergleich eine Abfrage gemacht, ob die beiden ID's schon miteinander verglichen wurden.
    Leider habe ich durch die ganzen If-Abfragen etwas den Überblick verloren und es werden nicht die richtigen Vergleiche gemacht, und nicht genug vergleiche.

    Eventuell sieht jemand von euch den Fehler?

    VB.NET-Quellcode

    1. Imports System.Linq
    2. Public Class Form1
    3. Dim respdict As Dictionary(Of Integer(), Double)
    4. Dim iddict As Dictionary(Of Integer(), Double)
    5. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6. Dim arr1 As Integer() = {1, 2, 3, 4, 10, 20, 30, 40, 50, 60}
    7. Dim arr2 As Integer() = {2, 3, 4, 5, 11, 21, 31, 41, 51, 61}
    8. Dim arr3 As Integer() = {3, 4, 5, 6, 12, 22, 32, 42, 52, 62}
    9. Dim arr4 As Integer() = {2, 3, 4, 5, 13, 23, 33, 43, 53, 63}
    10. Dim arr5 As Integer() = {1, 2, 3, 4, 14, 24, 34, 44, 54, 64}
    11. Dim arrlist As New List(Of Integer())
    12. arrlist.Add(arr1)
    13. arrlist.Add(arr2)
    14. arrlist.Add(arr3)
    15. arrlist.Add(arr4)
    16. arrlist.Add(arr5)
    17. iddict = New Dictionary(Of Integer(), Double)
    18. Dim id As Double = 1
    19. For Each iarr As Integer() In arrlist
    20. iddict.Add(iarr, id)
    21. id += 1
    22. Next
    23. respdict = New Dictionary(Of Integer(), Double)
    24. Dim comparedid(iddict.Count - 1) As String
    25. For Each arr As Integer() In arrlist
    26. For i = 0 To arrlist.Count - 2
    27. If comparedid IsNot Nothing Then
    28. Dim idmatch As String = iddict.Values(i).ToString + "," + iddict.Values(i + 1).ToString
    29. comparedid(i) = idmatch
    30. Dim equalnumbers = arr.Intersect(arrlist.Item(i + 1))
    31. Dim equalnumbersarr = equalnumbers.ToArray
    32. If respdict.ContainsKey(equalnumbersarr) = False Then
    33. respdict.Add(equalnumbersarr, 1)
    34. Else
    35. respdict.Item(equalnumbersarr) += 1
    36. End If
    37. Else
    38. Dim idmatch As String = iddict.Values(i).ToString + "," + iddict.Values(i + 1).ToString
    39. If comparedid.Contains(idmatch) = False Then
    40. Dim equalnumbers = arr.Intersect(arrlist.Item(i + 1))
    41. Dim equalnumbersarr = equalnumbers.ToArray
    42. If respdict.ContainsKey(equalnumbersarr) = False Then
    43. respdict.Add(equalnumbersarr, 1)
    44. Else
    45. respdict.Item(equalnumbersarr) += 1
    46. End If
    47. End If
    48. End If
    49. Next
    50. Next
    51. Dim maxvalue As Integer() = respdict.FirstOrDefault(Function(x) x.Value = respdict.Values.Max()).Key
    52. Dim outputstr As String = ""
    53. For Each integ As Integer In maxvalue
    54. If outputstr = "" Then
    55. outputstr = integ.ToString
    56. Else
    57. outputstr = outputstr + "," + integ.ToString
    58. End If
    59. Next
    60. TextBox1.Text = outputstr + " | " + respdict(maxvalue).ToString
    61. End Sub
    62. End Class
    @nicerdicer Welche von diesen soll er denn nun als "gleich" befinden?
    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!
    @RodFromGermany

    Bei den Arrays aus dem Code...

    VB.NET-Quellcode

    1. Dim arr1 As Integer() = {1, 2, 3, 4, 10, 20, 30, 40, 50, 60}
    2. Dim arr2 As Integer() = {2, 3, 4, 5, 11, 21, 31, 41, 51, 61}
    3. Dim arr3 As Integer() = {3, 4, 5, 6, 12, 22, 32, 42, 52, 62}
    4. Dim arr4 As Integer() = {2, 3, 4, 5, 13, 23, 33, 43, 53, 63}
    5. Dim arr5 As Integer() = {1, 2, 3, 4, 14, 24, 34, 44, 54, 64}


    ...Soll er folgende Vergleiche mit den folgenden Ergebnissen haben:


    arr1 mit arr2 -> 2,3,4arr1 mit arr3 -> 3,4arr1 mit arr4 -> 2,3,4arr1 mit arr5 -> 1,2,3,4
    arr2 mit arr3 -> 3,4,5arr2 mit arr4 -> 2,3,4,5arr2 mit arr5 -> 2,3,4
    arr3 mit arr4 -> 3,4,5arr3 mit arr5 -> 3,4
    arr4 mit arr5 -> 2,3,4

    Jetzt wo ich das schreibe bin ich mir doch sicher dass der Ansatz auch wieder nicht passt :( ... Hier wäre das Match "2,3,4" fünf anstatt vier Mal gekommen...Ich blicke ehrlich gesagt nicht mehr durch ?(
    @nicerdicer Wie sollen Lücken behandelt werden:
    {1,2,3,4,5}
    {1,2,4,5}
    ?
    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!
    @nicerdicer

    Hab ich da was in #8 falsches verstanden?

    Du möchtest doch jede Kombination prüfen oder, dass würde doch heissen du suchst eine K-Kombination ohne Wiederholung oder?

    Das macht aber dein Code nicht, soviel ich das erkennen kann.

    Hier kannst du alle Zahlen die in deiner Dict drin sind reingeben und die Kombinationsgrösse z.B. length = 2
    '1,2,3,4,5,6,10,11,12,13,14,20,21,22,23,24,30,31,32,33,34,40,41,42,43,44,50,51,52,53,54,60,61,62,63,64

    VB.NET-Quellcode

    1. Private Function ToCombination(Of T As IComparable)(list As IEnumerable(Of T), length As Int32) As IEnumerable(Of IEnumerable(Of T))
    2. If length = 1 Then Return list.[Select](Function(t0) New T() {t0})
    3. Return ToCombination(list, length - 1).SelectMany(Function(t0) list.Where(Function(o) o.CompareTo(t0.Last()) > 0), Function(t1, t2) t1.Concat(New T() {t2}))
    4. End Function


    Und jetzt noch mit den Werten in der Dict prüfen, das wird wahrscheinlich ein ziemlich grosse Anzahl an Kombinationen die nicht mehr kontrolliert werden kann. Wahrscheinlich stürzt VS dann ab.

    Freundliche Grüsse

    exc-jdbi


    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „exc-jdbi“ ()

    Danke @exc-jdbi , ich melde mich dann in einer Woche wenn ich die Funktion verstanden habe :thumbsup: .
    Ich teste das einmal und gebe dir Rückmeldung.

    Ich suche auf jeden Fall Wiederholungen.
    Nehmen wir an ich habe 100 Keys und Values in meinem Dictionary.
    Im Key sind die Zahlenkombinationen enthalten.

    In 40 der 100 Keys sind die Zahlen 1,2,3,4 im Array enthalten (auch gleichzeitig die häufigste Anzahl an Wiederholungen mit length=4)

    Die Funktion soll also folgendes Dictionary zurückgeben:

    Key
    {1,2,3,4}

    Value
    40

    ->Die am häufigsten in den 100 Keys enthaltene 4-stellige Zahlenfolge ist 1,2,3,4
    Also das möchte ich zumindest herausfinden.

    Oder z.B. die am häufigsten in den 100 Keys enthaltene 6-stellige Zahlenfolge (Rückgabe könnte Beispielsweise folgende sein: Key:{4,10,67,71,89,94}; Value:17 sofern die Zahlenfolge 17 mal vorkommt)

    nicerdicer schrieb:

    ich habe jetzt keine Funktion in dem Sinne verfasst, sondern habe versucht erst einmal alle Zahlenkombinationen jeweils miteinander abzugleichen
    Wie du wolle.
    Also du versuchst das Problem zu lösen, noch bevor du es überhaupt formuliert hast.
    Richte dich auf einen etwas längeren Thread ein... ;)
    Vollzitat des direkten Vorposts an dieser Stelle entfernt ~VaporiZed

    Hier der traurige Versuch deinen Vorschlag umzusetzen:

    Funktion:

    VB.NET-Quellcode

    1. Private Function GetSeriesOfNumbersByLength(ByVal arrayswithid As Dictionary(Of Integer(), Integer), ByVal sequencelength As Integer) As String
    2. 'Dictionary für die Datenverabeitung
    3. Dim workdict As New Dictionary(Of Integer(), Integer)
    4. For i = 0 To arrayswithid.Count - 1
    5. 'Irgendwas mit arrayswithid unter Berücksichtigung der sequencelength anstellen und in workdict überführen
    6. Next
    7. 'Höchsten Wert (Value) des Dictionarys workdict herausfinden
    8. Dim maxvalue As Integer() = workdict.FirstOrDefault(Function(x) x.Value = workdict.Values.Max()).Key
    9. 'Erster Teil Ausgabestring (Arrayinhalt to String)
    10. Dim retstring As String = ""
    11. For Each integ As Integer In maxvalue
    12. If retstring = "" Then
    13. retstring = integ.ToString
    14. Else
    15. retstring = retstring + "," + integ.ToString
    16. End If
    17. Next
    18. 'Zweiter Teil Ausgabestring (Zusammenführung des richten KeyValue-Paares von workdict)
    19. retstring = retstring + " | " + workdict(maxvalue).ToString
    20. Return retstring
    21. End Function



    Aufruf der Funktion:

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. 'Arrays erstellen und befüllen
    3. Dim arr1 As Integer() = {1, 2, 3, 4, 10, 20, 30, 40, 50, 60}
    4. Dim arr2 As Integer() = {2, 3, 4, 5, 11, 21, 31, 41, 51, 61}
    5. Dim arr3 As Integer() = {3, 4, 5, 6, 12, 22, 32, 42, 52, 62}
    6. Dim arr4 As Integer() = {2, 3, 4, 5, 13, 23, 33, 43, 53, 63}
    7. Dim arr5 As Integer() = {1, 2, 3, 4, 14, 24, 34, 44, 54, 64}
    8. 'Dictionary zum Übergeben erstellen und befüllen
    9. Dim iddict As New Dictionary(Of Integer(), Integer)
    10. iddict.Add(arr1, 1)
    11. iddict.Add(arr2, 2)
    12. iddict.Add(arr3, 3)
    13. iddict.Add(arr4, 4)
    14. iddict.Add(arr5, 5)
    15. TextBox1.Text = GetSeriesOfNumbersByLength(iddict, 6)
    16. End Sub

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

    @nicerdicer Also ich würde das so machen:
    Jedes Element mit jedem anderen vergleichen und feddich:

    VB.NET-Quellcode

    1. For i = 0 To liste.Lengrh - 1
    2. For j = 0 To liste.Lengrh - 1
    3. If i <> j Then
    4. ' VERGLEICHE(liste(i), liste(j))
    5. ' mit dem Resultat was tun
    6. End If
    7. Next
    8. Next
    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!