如果我在文本文件中有一个表格,例如
- AB 1
- 交流电 2
- 公元1
- 巴 3
- 光盘 2
- AE 1
- 编 2
- CB 2
- . . .
- . . .
- . . .
我在另一个文本文件中得到了另一个符号列表。我想将此表转换为 Perl 数据结构,例如:
- _阿德。. .
- 一个 0 1 1 。. .
- D 1 0 2 。. .
- E 1 2 0 。. .
- . . . . . . .
但我只需要一些选定的符号,例如在符号文本中选择了 A、D 和 E,但没有选择 B 和 C。
如果我在文本文件中有一个表格,例如
我在另一个文本文件中得到了另一个符号列表。我想将此表转换为 Perl 数据结构,例如:
但我只需要一些选定的符号,例如在符号文本中选择了 A、D 和 E,但没有选择 B 和 C。
第一个使用数组,第二个使用二维散列。第一个应该大致如下:
$list[0] # row 1 - the value is "A B 1"
哈希值如下:
$hash{A}{A} # the intersection of A and A - the value is 0
弄清楚如何解决问题对我来说大约是心理战的 75%。我不打算详细说明如何打印散列或数组,因为这很容易,而且我也不完全清楚您希望如何打印或打印多少。但是将数组转换为哈希应该看起来像这样:
foreach (@list) {
my ($letter1, $letter2, $value) = split(/ /);
$hash{$letter1}{$letter2} = $value;
}
至少,我认为这就是你要找的。如果您真的想要,您可以使用正则表达式,但这对于仅从字符串中提取 3 个值可能是过大的。
编辑:当然,您可以放弃@list
并直接从文件中组装散列。但这是你的工作,不是我的。
你可以用 awk 试试这个:
awk -f matrix.awk yourfile.txt > newfile.matrix.txt
其中 matrix.awk 是:
BEGIN {
OFS="\t"
}
{
row[$1,$2]=$3
if (!($2 in f2)) { header=(header)?header OFS $2:$2;f2[$2]}
if (col1[c]!=$1)
col1[++c]=$1
}
END {
printf("%*s%s\n", length(col1[1])+2, " ",header)
ncol=split(header,colA,OFS)
for(i=1;i<=c;i++) {
printf("%s", col1[i])
for(j=1;j<=ncol;j++)
printf("%s%s%c", OFS, row[col1[i],colA[j]], (j==ncol)?ORS:"")
}
}
另一种方法是制作一个二维数组 -
my @fArray = ();
## Set the 0,0th element to "_"
push @{$fArray[0]}, '_';
## Assuming that the first line is the range of characters to skip, e.g. BC
chomp(my $skipExpr = <>);
while(<>) {
my ($xVar, $yVar, $val) = split;
## Skip this line if expression matches
next if (/$skipExpr/);
## Check if these elements have already been added in your array
checkExists($xVar);
checkExists($yVar);
## Find their position
for my $i (1..$#fArray) {
$xPos = $i if ($fArray[0][$i] eq $xVar);
$yPos = $i if ($fArray[0][$i] eq $yVar);
}
## Set the value
$fArray[$xPos][$yPos] = $fArray[$yPos][$xPos] = $val;
}
## Print array
for my $i (0..$#fArray) {
for my $j (0..$#{$fArray[$i]}) {
print "$fArray[$i][$j]", " ";
}
print "\n";
}
sub checkExists {
## Checks if the corresponding array element exists,
## else creates and initialises it.
my $nElem = shift;
my $found;
$found = ($_ eq $nElem ? 1 : 0) for ( @{fArray[0]} );
if( $found == 0 ) {
## Create its corresponding column
push @{fArray[0]}, $nElem;
## and row entry.
push @fArray, [$nElem];
## Get its array index
my $newIndex = $#fArray;
## Initialise its corresponding column and rows with '_'
## this is done to enable easy output when printing the array
for my $i (1..$#fArray) {
$fArray[$newIndex][$i] = $fArray[$i][$newIndex] = '_';
}
## Set the intersection cell value to 0
$fArray[$newIndex][$newIndex] = 0;
}
}
我对我处理参考资料的方式并不感到太自豪,但在这里容忍初学者(请在评论中留下您的建议/更改)。上面提到的 Chris 的哈希方法听起来要容易得多(更不用说打字少了很多)。
CPAN有许多潜在有用的功能。我将Data::Table用于多种用途。Data::Pivot看起来也很有前途,但我从未使用过它。