2009-11-24 1 views
2

У меня есть файл csv со следующими данными образца.Как изменить поля в файле CSV с помощью Perl?

o-option(alphabetical) 
v-value(numerical) 

number1,o1,v1,o2,v2,o3,v3,o4,v4,o5,v5,o6,v6 
number2,o1,v11,o2,v22,o3,v33,o44,v44,o5,v55,o6,v66 

and so on.... 

Требуемый объем производства.

NUM,o1,o2,o3,o4,o44,o5,o6 
number1,v1,v2,v3,v4,,v5,v6 
number2,v11,v22,v33,,v44,v55,v66 

and so on... 

В этих данных, все варианты одинаковы т.е. o1, o2 и т.д. через из файла, но значение параметра 4 меняется, т.е. o4, O44 и т.д. В общей сложности насчитывается около 9 различных значений опций в o4. Может кто-нибудь, пожалуйста, помогите мне с кодом perl, чтобы получить требуемый результат.

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

my @values; 
my @options; 
my %hash; 

while (<STDIN>) { 
chomp; 
my ($srn,$o1,$v1,$o2,$v2,$o3,$v3,$o4,$v4,$o5,$v5,$o6,$v6) = split /[,\n]/, $_; 
push @values, [$srn,$v1,$v2,$v3,$v4,$v5,$v6]; 
push @options, $o1,$o2,$o3,$o4,$o5,$o6; 
} 

#printing the header values 
my @out = grep(!$hash{$_}++,@options); 
print 'ID,', join(',', sort @out), "\n"; 

#printing the values. 
for my $i (0 .. $#values) { 
     print @{$values[$i]}, "\n"; 
} 

Выход:

ID,o1,o2,o3,o4,o44,o5,o6 
number1,v1,v2,v3,v4,v5,v6 
number2,v1,v2,v3,v44,v5,v6 

Как из приведенного выше вывода, когда значение 44 приходит, оно попадает под ОПЦИЯ4 и, следовательно, остальные значения сдвига влево. Значения не сопоставляются с параметрами. Пожалуйста, предложите.

+0

Лучше всего предоставить конкретные данные, а не только o1, v1. Поместите в фактических количествах и материалах. Я не могу следовать тому, что вы хотите по этому образцу. – ghostdog74

ответ

2

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

use strict; 
use warnings; 

my (@data, %all_opts); 

while (<DATA>) { 
    chomp; 
    my %h = ('NUM', split /,/, $_); 
    push @data, \%h; 
    @all_opts{keys %h} = 1; 
} 

my @header = sort keys %all_opts; 
print join(",", @header), "\n"; 

for my $d (@data){ 
    my @vals = map { defined $d->{$_} ? $d->{$_} : '' } @header; 
    print join(",", @vals), "\n";  
} 


__DATA__ 
number1,o1,v1,o2,v2,o3,v3,o4,v4,o5,v5,o6,v6 
number2,o1,v11,o2,v22,o3,v33,o44,v44,o5,v55,o6,v66 
0

Сделайте один проход через файл, идентифицирующий все различные значения параметра, постройте массив этих значений.

сделать второй проход через файл:

for each record 
    initialise an associative array from your list of option value 
    parse the assigning values for the options you have 
    use your list of option values to iterate the associative array printing the values 
+0

@Virus Насколько велики файлы? Любые требования к производительности? (т. е. делать это в режиме реального времени)? – AndreaG

+0

@ Andrea: размер файла составляет от 70 до 80 мб. У меня нет проблем с чтением данных из файла. – Space

1

Это вы после?

use strict; 
use warnings; 
use 5.010; 

my %header; 
my @store; 

while (<DATA>) { 
    chomp; 
    my ($srn, %f) = split /,/; 
    @header{ keys %f } = 1; 
    push @store, [ $srn, { %f } ]; 
} 

# header 
my @cols = sort keys %header; 
say join q{,} => 'NUM', @cols; 

# rows 
for my $row (@store) { 
    say join q{,} => $row->[0], 
        map { $row->[1]->{ $_ } || q{} } @cols; 
} 

__DATA__ 
number1,o1,v1,o2,v2,o3,v3,o4,v4,o5,v5,o6,v6 
number2,o1,v11,o2,v22,o3,v33,o44,v44,o5,v55,o6,v66 

Какие выходы:

NUM,o1,o2,o3,o4,o44,o5,o6 
number1,v1,v2,v3,v4,,v5,v6 
number2,v11,v22,v33,,v44,v55,v66 
0

Вы можете посмотреть на модуль CPAN DBD::AnyData. Один из дополнительных модулей. Это позволяет вам манипулировать CSV-файлом, таким как база данных. И многое другое.

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