none
Zwei gruppierte Objekte (mit Count) zusammenführen RRS feed

  • Frage

  • Hallo an diesen warmen Sonnertag,

    erneut habe ich mal wieder ein Problem, welches, wie ich mir doch vorstelle, für euch kein Problem darstellt, für mich aber dennoch unlösbar erscheint!

    Der Titel der Frage scheint etwas merkwürdig (ich wüsste nicht, wie ich mich besser ausdrucken soll), aber wie so oft kann ein Beispiel alles näher bringen!

    Okay, gehen wir mal von einer Textdatei "complete" aus, die wie folgt aussieht:

    Klaus
    Gabi
    Klaus
    Klaus
    Steffan
    Gabi


    In Gruppen sieht das so aus (sprich: gc complete.txt | group | select-object -property Name,count)

    Name                                                                      Count
    ----                                                                      -----
    Klaus                                                                         3
    Gabi                                                                          2
    Steffan                                                                       1
    
    


    So, jetzt haben wir noch eine zweite Textdatei ("today") die ohne Gruppen so aussieht:

    Klaus Klaus Steffan Harald

    Und nach Group so aussieht (sprich gc today.txt | group | select-object -property Name,count)

    Name                                                                      Count
    ----                                                                      -----
    Klaus                                                                         2
    Steffan                                                                       1
    Harald                                                                        1
    

    So, ich denke soweit ist alles noch klar.

    Wie kann ich diese beiden ("gegroupten" / sortierten) Textdateien zusammenführen, sodass der Count addiert wird (z.B. für Klaus 5).

    So sollte das aussehen:

    Name                                                                      Count
    ----                                                                      -----
    Klaus                                                                         5
    Gabi                                                                          2
    Steffan                                                                       2
    Harald                                                                        1

    Habe schon einiges nachgeforscht, aber für mein Problem noch nichts gefunden (oder ich war zu blöd, es darauf anzuwenden).

    Ich danke schonmal vielmals und noch einen schönen (ja, sowas gibt es wieder in Deutschland) Sommertag!

    Konstantin.

    Freitag, 17. August 2012 15:11

Antworten

  • Hallo,

    den Ansatz würde ich auch verfolgen, nur die ForEach-Schleift in Deinem Beispiel würde ich auf jeden Fall austauschen. Wenn man zwei Dateien mit relativ wenigen Datensätzen hat, ist die Methode zu tolerieren. Jedoch ab 5000 Einträgen dauert die Methode wesentlich länger. Die Erweiterung eines Arrays über den += Operator ist extrem teuer, weil die vorhandenen Daten jedes Mal an eine neue Adresse kopiert werden müssen.

    Das folgende Script macht einen zeitlichen Vergleich zwischen ca. 10.000x ForEach mit += und nur einmal einem +=.

    PS C:\Users\raandree\Dropbox\Desktop> .\join.ps1
    Sample 1: 00:03:15.6926225
    Sample 2: 00:00:34.4350512

    $start = Get-Date
    $a = gc e:\names1.txt
    $b = gc e:\names2.txt
    
    $joinedObject = $a
    foreach ($name in $b) { $joinedObject += $name}
    $joinedObject | group | select-object -property Name,count
    $end = Get-Date
    "Sample 1: $($end - $start)"
    
    $start = Get-Date
    $joinedObject = gc e:\names1.txt
    $joinedObject += gc e:\names2.txt
    
    $joinedObject | group | select-object -property Name,count
    $end = Get-Date
    "Sample 2: $($end - $start)"


    -Raimund

    Samstag, 18. August 2012 21:28
  • Du hast recht. Es muß wohl am Wetter liegen, so gehts auch: :)

     

    $start = get-date
    $a = gc d:\names1.txt
    $b = gc d:\names2.txt
    
    $joinedObject = $a + $b 
    $joinedObject | group | select-object -property Name,count
    
    "Seconds: $(((get-date)-$start).totalseconds)"

    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".

    Montag, 20. August 2012 16:09
    Moderator

Alle Antworten

  • Am einfachsten wird es sein, ein gemeinsames Object zu erstellen und dies dann auszuwerten (gruppieren etc):
     

    $a = gc d:\1.txt
    $b = gc d:\2.txt
    
    $joinedObject = $a
    foreach ($name in $b) { $joinedObject += $name}
    $joinedObject | group | select-object -property Name,count
     

    Falls du komplexere Dateien (und damit Objekte) hast, gehts nicht ganz so einfach, geht aber auch. Schau mal hier: LINK

    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".



    Freitag, 17. August 2012 15:47
    Moderator
  • Hallo,

    den Ansatz würde ich auch verfolgen, nur die ForEach-Schleift in Deinem Beispiel würde ich auf jeden Fall austauschen. Wenn man zwei Dateien mit relativ wenigen Datensätzen hat, ist die Methode zu tolerieren. Jedoch ab 5000 Einträgen dauert die Methode wesentlich länger. Die Erweiterung eines Arrays über den += Operator ist extrem teuer, weil die vorhandenen Daten jedes Mal an eine neue Adresse kopiert werden müssen.

    Das folgende Script macht einen zeitlichen Vergleich zwischen ca. 10.000x ForEach mit += und nur einmal einem +=.

    PS C:\Users\raandree\Dropbox\Desktop> .\join.ps1
    Sample 1: 00:03:15.6926225
    Sample 2: 00:00:34.4350512

    $start = Get-Date
    $a = gc e:\names1.txt
    $b = gc e:\names2.txt
    
    $joinedObject = $a
    foreach ($name in $b) { $joinedObject += $name}
    $joinedObject | group | select-object -property Name,count
    $end = Get-Date
    "Sample 1: $($end - $start)"
    
    $start = Get-Date
    $joinedObject = gc e:\names1.txt
    $joinedObject += gc e:\names2.txt
    
    $joinedObject | group | select-object -property Name,count
    $end = Get-Date
    "Sample 2: $($end - $start)"


    -Raimund

    Samstag, 18. August 2012 21:28
  • Hey,

    danke euch beiden für eure Antworten!

    Werd mir eure Ansätze mal genauer angucken. Vielen Dank!

    Dann noch einen schönen Tag.

    Montag, 20. August 2012 11:52
  • Du hast recht. Es muß wohl am Wetter liegen, so gehts auch: :)

     

    $start = get-date
    $a = gc d:\names1.txt
    $b = gc d:\names2.txt
    
    $joinedObject = $a + $b 
    $joinedObject | group | select-object -property Name,count
    
    "Seconds: $(((get-date)-$start).totalseconds)"

    Grüße, Denniver


    Blog: http://bytecookie.wordpress.com

    Hilf mit und markiere hilfreiche Beiträge als "Hilfreich" und Beiträge die deine Frage ganz oder teilweise beantwortet haben als "Antwort".

    Montag, 20. August 2012 16:09
    Moderator