2015-03-20 1 views
1

У меня есть файл CSV,Как объединить записи в файл csv на основе первого поля?

id1,v1,v2,v3,v4 
id2,v1,v2,v6,v4 
id1,v7,v8,v3,v9 
id1,v10,v11,v12,v13 
id2,v3,v5,v8,v7 

так, файл не отсортирован, и не должно быть! Я хочу выход как:

id1,v1|v7|v10,v2|v8|v11,v3|v12,v4|v9|v13 
id2,v1|v10,v2|v5,v6|v8,v4|v7 

Где все соответствующие значения в колонках объединяются в соответствующем столбце в записи с одинаковым идентификатором, за исключением повторного значения (см v3 в 3-м столбце ID1) и ид.

Я попробовал это, используя приведенный здесь код http://www.robelle.com/tips/st-export-notes.html. Но ему нужно гораздо больше.

Как это можно достичь с помощью perl? Я новичок в perl. Заранее спасибо!

+0

ли трубы, разделенные составные поля, необходимые, чтобы быть в порядке их появления в файле ? Например, это 'id1, v10 | v1 | v7, ...' okay? – Borodin

+0

@Borodin, извините за поздний ответ, заказ не имеет значения. –

ответ

1

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

use strict; 
use warnings; 

my %data; 

while (<DATA>) { 
    my ($id, @vals) = /[^,\s]+/g; 
    for my $i (0 .. $#vals) { 
    ++$data{$id}[$i]{$vals[$i]}; 
    } 
} 

while (my ($id, $vals) = each %data) { 
    my @vals = map { join '|', keys %$_ } @$vals; 
    printf "%s,%s\n", $id, join ',', @vals; 
} 

__DATA__ 
id1,v1,v2,v3,v4 
id2,v1,v2,v6,v4 
id1,v7,v8,v3,v9 
id1,v10,v11,v12,v13 
id2,v3,v5,v8,v7 

выход

id2,v1|v3,v5|v2,v8|v6,v7|v4 
id1,v7|v10|v1,v11|v2|v8,v12|v3,v4|v13|v9 
+0

Прошу прощения: мое оригинальное решение было неправильным, потому что я неправильно понял ваш вопрос. Это должно быть прямо сейчас – Borodin

+0

Большое спасибо @Borodin, его идеальный ans. Я просто удалил $ fh в printf и добавил «open (DATA,«

+0

@NTN: Я рад помочь. Я сожалею о постороннем '$ fh' - это было наследие моего тестирования. – Borodin

-1

Вы должны использовать правильную CSV парсер для данных CSV

use strict; 
use warnings; 
use Text::CSV; 

my $csv = Text::CSV->new({ binary => 1, eol => $/ }); 

my %data; 
while (my $row = $csv->getline(*DATA)) { 
    my $id = shift @$row; 
    $data{$id}[$_]{ $$row[$_] } = undef for 0 .. $#$row; 
} 

for my $id (sort keys %data) { 
    my $vals = $data{$id}; 
    $csv->print(\*STDOUT, [ $id, map { join '|', sort keys %$_ } @$vals ]); 
} 

__DATA__ 
id1,v1,v2,v3,v4 
id2,v1,v2,v6,v4 
id1,v7,v8,v3,v9 
id1,v10,v11,v12,v13 
id2,v3,v5,v8,v7 

 Смежные вопросы

  • Нет связанных вопросов^_^