3 Stimmen

Entfernen überflüssiger Felder und Zusammenführen der resultierenden Zeilen

Ich versuche, eine einfache Textdatei zu verarbeiten. Es handelt sich im Wesentlichen um einen Index von Namen und zugehörigen Zahlenfeldern, die wie folgt formatiert sind:

Nowosielski, Matthäus, 484, 584, 777
Nowosielski, Matthäus, 1151
Nunes, Paulino, 116
Nussbaum, Mike, 1221, 444,
Nussbaum, Mike, 156

Diese möchte ich zu folgendem verarbeiten

Nowosielski, Matthäus, 484, 584, 777, 1151
Nunes, Paulino, 116
Nussbaum, Mike, 156, 444, 1221

Wie Sie sehen können, enden die Zeilen nicht einheitlich: einige sind wahrscheinlich Leerzeichen, einige Zeilenumbrüche und einige mit Kommas. Ich muss also Zeilen zusammenführen, die mit doppelten vollständigen Namen beginnen, wobei der redundante Namenseintrag beim Zusammenführen verworfen und die numerische Reihenfolge der numerischen Felder beibehalten wird.

Mein Bauchgefühl sagt mir, dass ich entweder schnell Perl oder awk lernen sollte, aber meine Kenntnisse sind für beides leer. Ich schaute in beide, und nach einigen suchen und Lesen nicht in der Lage gewesen, einen klaren oder sauberen Weg zu einer Lösung zu finden.

Meine Frage lautet daher: Was wäre das beste Werkzeug für diese Aufgabe, das ich effizient und gerade ausreichend erlernen könnte, um diese Aufgabe zu bewältigen? Gibt es angesichts des vorgeschlagenen Werkzeugs irgendwelche Vorschläge, wie ich das Problem angehen könnte?

Ich kann diese Datei natürlich auch von Hand bearbeiten, aber das ist nicht sehr interessant und scheint mir eine sehr dumme, ungeschickte Herangehensweise an das Problem zu sein. Ich nehme diese Aufgabe zum Anlass, etwas über Textverarbeitung zu lernen, da ich das Gefühl habe, dass es für dieses Problem wahrscheinlich ein gutes, vorhandenes Werkzeug gibt.

Haben Sie einen Tipp?

4voto

Pedro Silva Punkte 4602

Wie Brian sagte, verwenden Sie eine Hashtabelle. Im Folgenden werden Zeilenumbrüche entfernt, die einzelnen Datensätze durch Kommas getrennt, die ursprüngliche Form "Nachname, Vorname" als Schlüssel für einen Hash verwendet, die verbleibenden Werte in ein Array verschoben und ein Verweis auf dieses Array als Wert für den oben genannten Schlüssel verwendet.

Dann werden einfach die Schlüssel/Wertpaare im Hash durchlaufen und entsprechend formatiert.

Geänderte Lösung - Sortierung der Zahlen, Weglassen der zweiten Vornamen und Sortierung der Ausgabe

#!/usr/bin/env perl
use strict;
use warnings;

my %merged;

while (my $record = <DATA>) {
    chomp $record;
    my ($lname, $fname, @stuff) = split /[, ]+/, $record;
    push @{ $merged{"$lname, $fname"} }, grep { m/^\d+$/; } @stuff;
}

foreach my $name (sort keys %merged) {
    print $name, ", ", join( ', ', sort { $a <=> $b } @{$merged{$name}}), "\n";
}

__DATA__
Nowosielski, Matthew, 484, 584, 777
Nowosielski, Matthew, 1151
Nunes, Paulino, 116
Nussbaum, Mike, 1221, 444,
Nussbaum, Mike, 156
Nowosielski, Matthew, Kimball, 485, 684, 277

Geänderte Ausgabe

Nowosielski, Matthew, 277, 484, 485, 584, 684, 777, 1151
Nunes, Paulino, 116
Nussbaum, Mike, 156, 444, 1221

Ursprüngliche Lösung

#!/usr/bin/env perl
use strict;
use warnings;

my %merged;

while (my $record = <DATA>) {
    chomp $record;
    my ($lname, $fname, @stuff) = split /,/, $record;

    push @{ $merged{"$lname, $fname"} }, @stuff;
}

while (my ($name, $stuff) = each %merged) {
    print $name, join( ',', @$stuff), "\n"; 
}

__DATA__
Nowosielski, Matthew, 484, 584, 777
Nowosielski, Matthew, 1151
Nunes, Paulino, 116
Nussbaum, Mike, 1221, 444,
Nussbaum, Mike, 156

2voto

Brian Clements Punkte 3619

Da ich dies als Vorwand zum Lernen sah, schrieb ich ein schnelles Python-Skript.

Erstellen Sie sich ein Wörterbuch (Map) mit Zeichenketten als Schlüssel und Werte. Lesen Sie eine Zeile ein und erfassen Sie den Namen. Schlagen Sie den Namen im Wörterbuch nach. Wenn er dort steht, hängen Sie die neuen Zahlen an das Ende des Wörterbucheintrags an. Wenn Sie die gesamte Datei gelesen haben, gehen Sie das Wörterbuch durch und geben Sie die Schlüssel und Werte aus.

1voto

Jonathan Leffler Punkte 694013

Um dies sauber zu tun, brauchen Sie eine Sprache mit assoziativen Arrays (Perl - Hashes; Python - Dictionaries; Awk - assoziative Arrays). Das schließt aus sed (und C).

En awk :

awk '{ for (i = 3; i <= NF; i++) {names[$1, $2] = names[$1, $2] " " $i } }
     END { for (name in names) { printf "%s: %s\n", name, names[name]; } }'

Sie könnten es vorziehen, das Komma als Feldbegrenzer mit ' -F, '.

Die zusätzlichen Anforderungen - Sortieren von Zahlen in der richtigen Reihenfolge und Behandlung von Mittelnamen - sind in awk als perl mit den zusätzlichen Anforderungen, würde ich mich für perl statt awk . (Beachten Sie, dass GNU Awk eingebaute Funktionen hat asort y asorti um Arrays zu sortieren, aber ich bin mir nicht sicher, ob man mit ' names[$1,$2] Identifizierung einer Reihe von Ganzzahlen in awk .) Ich beherrsche Perl viel besser als Python - aber was Perl kann, kann Python zweifellos auch.

0voto

cryptochaos Punkte 21

Versuchen Sie es mit AWK

#!/usr/bin/awk -f
$1 == lastOne && $2 == lastTwo { $1=""; $2=""; printf ", %s", $0 ;lastOne=$1; lastTwo=$2 }
$1 != lastOne && $2 != lastTwo { printf "\n%s", $0 ;lastOne=$1; lastTwo=$2 }
END {printf "\n" }

Dieses Skript geht davon aus, dass die Daten nach den ersten beiden Feldern sortiert sind...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X