문제

텍스트 파일에 테이블이있는 경우

  • AB 1
  • AC 2
  • AD 1
  • BA 3
  • CD 2
  • ae 1
  • 에드 2
  • CB 2
  • . . .
  • . . .
  • . . .

다른 텍스트 파일에 다른 기호 목록이 있습니다. 이 테이블을 다음과 같은 PERL 데이터 구조로 변환하고 싶습니다.

  • _ ade. . .
  • A 0 1 1. . .
  • D 1 0 2. . .
  • E 1 2 0. . .
  • . . . . . . .

그러나 선택한 기호 만 필요합니다 (예 : a, d 및 e는 기호 텍스트에서 선택되지만 b와 c는 그렇지 않습니다.

도움이 되었습니까?

해결책

첫 번째 배열에는 배열을 사용하고 두 번째는 2 차원 해시를 사용하십시오. 첫 번째는 대략적인 모습을 보여야합니다.

$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:"")
  }
}

이렇게하는 또 다른 방법은 2 차원 배열을 만드는 것입니다.

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 많이있다 잠재적으로 유용한 Suff. 나는 사용한다 데이터 :: 테이블 많은 목적을 위해. 데이터 :: 피벗 또한 유망 해 보이지만 나는 그것을 사용한 적이 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top