Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 如何将表格转换为矩阵?_Perl_Hash_Matrix_Perl Data Structures - Fatal编程技术网

Perl 如何将表格转换为矩阵?

Perl 如何将表格转换为矩阵?,perl,hash,matrix,perl-data-structures,Perl,Hash,Matrix,Perl Data Structures,如果我在这样的文本文件中有一个表 A B 1 A C 2 A D 1 B A 3 C D 2 A E 1 E D 2 C B 2 我在另一个文本文件中得到了另一个符号列表。我想将此表转换为Perl数据结构,如: _A D E 一个0 1 1 D 1 0 2 E120 但我只需要一些选定的符号,例如,符号文本中选择了A、D和E,但B和C没有选择。第一个符号使用数组,第二个符号使用二维哈希。第一个应该大致如下所示: $list[0] # row 1 - the value is "A

如果我在这样的文本文件中有一个表

  • A B 1
  • A C 2
  • A D 1
  • B A 3
  • C D 2
  • A E 1
  • E D 2
  • C B 2
我在另一个文本文件中得到了另一个符号列表。我想将此表转换为Perl数据结构,如:

  • _A D E
  • 一个0 1 1
  • D 1 0 2
  • E120

但我只需要一些选定的符号,例如,符号文本中选择了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
,直接从文件中组装哈希。但这是你的工作,不是我的。

另一种方法是制作一个二维数组-

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;
    }
}
my@fArray=();
##将第0,0个元素设置为“\u0”
推送{$fArray[0]},';
##假设第一行是要跳过的字符范围,例如BC
chomp(我的$skipExpr=);
while(){
我的($xVar,$yVar,$val)=分割;
##如果表达式匹配,则跳过此行
下一个if(/$skipExpr/);
##检查这些元素是否已添加到数组中
支票存在($xVar);
支票存在($yVar);
##找到他们的位置
为了我的$i(1..$#fArray){
$xPos=$i if($fArray[0][$i]eq$xVar);
$yPos=$i if($fArray[0][$i]eq$yVar);
}
##设置值
$fArray[$xPos][$yPos]=$fArray[$yPos][$xPos]=$val;
}
##打印阵列
对于我的$i(0..$#fArray){
对于我的$j(0..$#{$fArray[$i]}){
打印“$fArray[$i][$j]”,“”;
}
打印“\n”;
}
子支票存在{
##检查对应的数组元素是否存在,
##else创建并初始化它。
我的$nElem=班次;
我的美元找到了;
$found=(${fArray[0]})的($eq$nElem?1:0);
如果($found==0){
##创建相应的列
推{fArray[0]},$nElem;
##和行输入。
推@fArray,[$nElem];
##获取其数组索引
我的$newIndex=$#fArray;
##用“\”初始化其相应的列和行
##这样做是为了在打印阵列时方便输出
为了我的$i(1..$#fArray){
$fArray[$newIndex][$i]=$fArray[$i][$newIndex]='';
}
##将相交单元值设置为0
$fArray[$newIndex][$newIndex]=0;
}
}

对于我处理推荐信的方式,我不太自豪,但请容忍这里的初学者(请在评论中留下您的建议/更改)。上面提到的Chris的hash方法听起来简单得多(更不用说打字量少了)。

有很多。我使用它有很多用途。看起来也很有希望,但我从未使用过它。

您可以用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:"")
  }
}
开始{
OFS=“\t”
}
{
行[$1,$2]=$3
如果(!(f2中的$2)){header=(header)?S$2的头:$2;f2[$2]}
如果(col1[c]!=1美元)
col1[++c]=1美元
}
结束{
printf(“%*s%s\n”,长度(col1[1])+2,”,标题)
ncol=拆分(收割台、可乐、OFS)

对于(i=1;i)你的问题对我来说很不清楚。你能重新解释一下吗?如果散列键足够简单,你可以使用一个散列来连接键。所以$hash{AD}保持1。如果使用得当,此方法可以简化代码。如果使用不当,会导致出现奇怪的错误和难看的代码。此技术应仅用于非常简单的哈希键。我尝试使用哈希,但在打印值时出现一些问题。我的代码发布在下面(回答4)。请看一看。谢谢!-Debbie如果我将所有必需的字符保存到数组@all_node中。我可以将“next if(/$skipExpr/);”更改为“next除非(/@all_node/);”?数组@all_node将在列表分隔符变量的帮助下进行插值-$默认情况下,它设置为一个空格“”。因此它可以工作,但在正则表达式中使用数组之前需要将其设置为“”。local$“=”;next,除非(/@all_node/);