Как удалить лишние поля и объединить результирующие строки - PullRequest
3 голосов
/ 02 ноября 2010

Я пытаюсь обработать простой текстовый файл. Это в основном индекс имен и связанных числовых полей, отформатированных так:

Новосельский, Матфей, ​​484, 584, 777
Новосельский, Матфей, ​​1151
Нунес, Паулино, 116
Нуссбаум, Майк, 1221, 444,
Нуссбаум, Майк, 156

Что я хотел бы обработать в этом

Новосельский, Матфей, ​​484, 584, 777, 1151
Нунес, Паулино, 116
Нуссбаум, Майк, 156, 444, 1221

Как видите, строки не заканчиваются последовательно: некоторые, скорее всего, будут пробелами, некоторые - новыми, а некоторые - запятыми. По сути, мне нужно объединить строки, начинающиеся с дублированных полных имен, отбрасывая лишнюю запись имени при объединении и сохранении числового порядка числовых полей.

Моя интуиция говорит мне, чтобы я выучил какой-нибудь быстрый perl или awk, но мой набор навыков для обоих пуст. Я изучил оба, и после некоторого поиска и чтения не смог найти ясного или чистого пути к решению.

Мой вопрос, таким образом, таков: какой будет лучший инструмент для работы, который я мог бы освоить эффективно и достаточно просто для выполнения этой задачи? Кроме того, учитывая предложенный инструмент, есть ли какие-либо предложения о том, как подойти к проблеме?

Конечно, я могу просто отредактировать этот файл вручную, но это не очень интересно, и кажется, что это очень глупый, тупой подход к проблеме. Я воспринимаю эту задачу как предлог, чтобы немного узнать об обработке текста, так как это похоже на проблему, для которой, вероятно, есть хороший, существующий инструмент.

Есть указатели?

Ответы [ 4 ]

4 голосов
/ 02 ноября 2010

Как сказал Брайан, используйте хеш-таблицу. Следующее удаляет переводы строк, разделяет каждую запись на запятые, использует исходную форму «фамилия, имя» в качестве ключа к хешу, помещает оставшиеся значения в массив и использует ссылку на указанный массив в качестве значения для указанного выше ключа. .

Затем он просто перебирает пары ключ / значение в хэше и соответственно форматирует.

Исправленное решение - сортировка чисел, пропуск средних имен и вывод сортировки

#!/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

Исправленный вывод

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

Оригинальное решение

#!/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
2 голосов
/ 02 ноября 2010

Рассматривая это как предлог для изучения, я бы написал быстрый скрипт на python.

Создайте себе словарь (карту) со строками в качестве ключей и значений.Прочитайте в строке и захватите имя.Посмотрите имя в словаре.Если оно там, добавьте новые номера в конец словарной статьи.Прочитав весь файл, выполните итерацию по словарю и распечатайте ключи и значения.

1 голос
/ 02 ноября 2010

Чтобы сделать это чисто, вам нужен язык с ассоциативными массивами (Perl - хэши; Python - словари; Awk - ассоциативные массивы). Это исключает sed (и C).

В 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]; } }'

Вы можете указать запятую как разделитель полей с помощью -F,.

Дополнительные требования - сортировка номеров по порядку и обработка отчеств - гораздо проще в awk, чем perl; с дополнительными требованиями я бы выбрал perl вместо awk. (Обратите внимание, что в GNU Awk есть встроенные функции asort и asorti для сортировки массивов, но я не уверен, что у вас может быть 'names[$1,$2], идентифицирующий массив целых чисел в awk.) Я гораздо больше Свободнее владеет Perl, чем Python, но Python, несомненно, может делать то же, что и Perl.

0 голосов
/ 12 ноября 2010

Попробуйте использовать 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" }

Этот сценарий предполагает, что данные отсортированы в ваших первых двух полях ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...