Я написал скрипт на Perl, который принимает XML, анализирует его и создает CSV.Взятие xml, его синтаксический анализ и сортировка, кажется, идут очень гладко, но как только я попадаю в большие наборы данных (т.е. создаю csv с 10000 строками и 260 столбцами), сценарий начинает занимать огромное количество времени (~ 1 час), покапостроение строки CSV.Я понимаю, что Perl, вероятно, не лучший для объединения строк;но я бы подумал, что это было бы более эффективно, чем это.
В принципе, для сортировки у меня есть два хэша массивов.Один хеш содержит массивы, которые я использовал для сортировки.Другой хеш содержит массивы для всех других столбцов (столбцы, которые я хочу записать в CSV; но не имеют отношения к тому, как я хочу их отсортировать).Таким образом, мой код проблемы (и я убедился, что это блок кода, принимающий навсегда) код выглядит так:
my $csv = "Header1, Header2, Header3, Header4,...,HeaderN-1,HeaderN\n";
foreach my $index (@orderedIndecies) {
my @records = @{$primaryFields{"Important Field 1"}};
$csv .= $records[$index] ? "$records[$index]," : ",";
$csv .= $primaryIndex[$index] >= 0 ? "$primaryIndex[$index]," : ",";
@records = @{$primaryFields{"Important Field 2"}};
$csv .= $records[$index] ? "$records[$index]," : ",";
foreach my $key (@keys) {
@records = @{$csvContent{$key}};
if($key eq $last) {
$csv .= $records[$index] ? "$records[$index]\n" : "\n";
} else {
$csv .= $records[$index] ? "$records[$index]," : ",";
}
}
}
Я также пробовал то же самое, используя только метод соединения вместо ". =".Я также попытался исключить агрегирование строк и записать их непосредственно в файл.И то и другое не очень помогло.Я буду первым, кто признает, что мои знания по управлению памятью в Perl, вероятно, не самые лучшие;поэтому, пожалуйста, не стесняйтесь учить меня (конструктивно).Кроме того, если вы думаете, что это то, что я должен рассмотреть переписать за пределами Perl, пожалуйста, дайте мне знать.
РЕДАКТИРОВАТЬ: Некоторые примеры XML (пожалуйста, имейте в виду, что я не в состоянии редактировать структуруxml):
<fields>
<field>
<Name>IndicesToBeSorted</Name>
<Records>idx12;idx14;idx18;...idxN-1;idxN</Records>
</field>
<field>
<Name>Important Field1</Name>
<Records>val1;val2;;val4;...;valn-1;valn</Records>
</field>
<field>
<Name>Important Field2</Name>
<Records>val1;val2;;val4;...;valn-1;valn</Records>
</field>
<field>
<Name>Records...</Name>
<Records>val1;val2;;val4;...;valn-1;valn</Records>
</field>
<field>
<Name>More Records...</Name>
<Records>val1;val2;;val4;...;valn-1;valn</Records>
</field>
</fields>
Позиция записи в одном поле соответствует позиции в другом поле.Например;первый элемент из каждого элемента «Записи» связан и составляет столбец в моем CSV.В общем, мой сценарий анализирует все это и создает массив упорядоченных индексов (что и есть в @orderedIndecies в моем примере).@OrderdIndecies содержит такие данные, как ...
print "$orderedInecies[0]\n" #prints index of location of idx0
print "$orderedInecies[1]\n" #prints index of location of idx1
print "$orderedInecies[2]\n" #prints index of location of idx2
print "$orderedInecies[3]\n" #prints index of location of idx3
Я делаю все так, потому что строка orderIndecies вышла из строя;и я не хотел перемещать все данные.
РЕДАКТИРОВАТЬ: ФИНАЛЬНЫЙ ОТВЕТ
open my $csv_fh, ">", $$fileNameRef or die "$$fileNameRef: $!";
print $csv_fh "Important Field 1,Index Field,Important Field 2";
# Defining $comma, $endl, $empty allows me to do something like:
#
# print $csv_fh $val ? $val : $empty;
# print $csv_fh $comma;
#
# As opposed to....
#
# print $csv_fh $val ? "$val," : ",";
#
# Note, the first method avoids the string aggregation of "$val,"
my $comma = ",";
my $endl = "\n";
my $empty = "";
my @keys = sort(keys %csvContent);
my $last = $keys[-1];
foreach (@keys) {
print $csv_fh $_;
print $csv_fh $_ eq $last ? $endl : $comma;
}
# Even though the hash lookup is probably very efficient, I still
# saw no need to redo it constantly, so I defined it here as
# opposed to inline within the for loops
my @ImportantFields1 = @{$primaryFields{"Important Field 1"}};
my @ImportantFields2 = @{$primaryFields{"Important Field 2"}};
print "\n\n--------- BUILD CSV START ---------------\n\n";
foreach my $index (@orderedIndecies) {
print $csv_fh exists $ImportantFields1[$index] ? $ImportantFields1[$index] : $empty;
print $csv_fh $comma;
print $csv_fh $originalIndexField[$index] >= 0 ? $originalIndexField[$index] : $empty;
print $csv_fh $comma;
print $csv_fh exists $ImportantFields2[$index] ? $ImportantFields2[$index] : $empty;
#If needed, this is where you would make sure to escape commas
foreach my $key (@keys) {
print $csv_fh $comma;
$record = exists @{$csvContent{$key}}[$index]
? @{$csvContent{$key}}[$index];
: $empty;
}
print $csv_fh $endl;
}
print "\n\n------- CSV Contents wrtten to file -----------\n\n"
close($csv_fh);
Спасибо за помощь, ребята: D