perl에서 xml을 파싱하고 구문 분석 한 다음 csv를 빌드하는 스크립트를 작성했습니다. xml을 가져 와서 파싱하고 정렬하는 것은 매우 원활하게 진행되는 것 같습니다. 그러나 일단 큰 데이터 세트 (예 : 10000 개의 행과 260 개의 열이있는 csv를 작성)로 들어가면 스크립트는 엄청난 시간 (~ 1 시간)을 소비하기 시작합니다. csv 문자열을 작성합니다. 필자는 Perl이 아마도 문자열 연결에 가장 좋지 않다는 것을 알고 있습니다. 그러나 나는 이것보다 더 효율적이라고 생각했을 것이다.perl에서 csv를 빌드하는 중에 발생하는 문제
기본적으로 정렬을 위해 두 개의 배열 해시가 있습니다. 하나의 해시에는 정렬에 사용한 배열이 들어 있습니다. 다른 해시에는 다른 모든 열 (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에서의 메모리 관리에 대한 나의 지식이 아마도 가장 크지 않다는 것을 인정하는 첫 번째 사람이 될 것이다. 제발 학교에 나눠주세요. (건설적으로). 또한, 이것이 펄의 외부에서 재 작성하는 것을 고려해야한다고 생각된다면 알려주십시오.
편집 : 일부 샘플 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는 orderedIndecies에서 문자열 순서가 있기 때문에 나는이 일이 방법을
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
... 같은 데이터를 포함하고; 나는 모든 데이터를 옮기고 싶지 않았다.
편집 : 도움말들에 대한 최종 답변
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
샘플 XML 및 예상되는 CSV 출력을 보지 않고도 자신이 무엇을하고 있는지 말할 수는 없습니다. 또한 이것은 아마도 XSLT를 사용하는 것보다 쉽다 (또는 매우 쉽다). –
샘플 xml로 업데이트되었습니다. xslt를 사용하는 것이 훨씬 더 효율적입니까? 내가 가지고있는 XML이 잘 구조화되어 있지 않다는 것과 xslt 내부에서 문자열 분석을위한 논리를 많이 가져야 만 원하는 결과를 얻을 수있는 CSV를 얻을 수 있다는 것을 알고 있습니다. 특히 행의 내용을 정렬해야하기 때문에 특히 그렇습니다. xslt는 여전히 고려해야 할 사항입니까? – Dave
사실, perl은 문자열을 조작하기위한 훌륭한 도구입니다. 이것은 주요 목적 중 하나입니다. 알고리즘이 오래 걸리는 이유는 알고리즘 자체입니다. O (N^2)입니다. 언어에 관계없이, 그것은 연결하기 위해 260 만 값으로 오랜 시간이 걸릴 것입니다. 할당해야하고 매번 다시 할당해야합니다 (거의 perl은 일반적으로 그것에 대해 영리합니다). 그런 종류의 작업을 수행합니다. –