Annoying hash in perl
산열 된 배열
만약 기록 이 한 무더기 있다 면, 순서대로 그것들 을 방문 하고 싶 으 며, 모든 기록 자체 에 키 / 수치 가 포함 되 어 있 으 면, 흩 어 진 배열 이 매우 유용 하 다.이 장 에 서 는 산열 된 배열 이 다른 구조 보다 조금 적다.
1. 산열 된 배열 을 구성한다.
다음 방법 으로 익명 으로 흩 어 진 배열 을 만 들 수 있 습 니 다:
@AoH = (
{
husband => "barney",
wife => "betty",
son => "bamm bamm",
},
{
husband => "george",
wife => "jane",
son => "elroy",
},
{
husband => "homer",
wife => "marge",
son => "bart",
},
);
배열 에 다른 해시 를 추가 하려 면 간단하게 말 할 수 있 습 니 다.
push @AoH, { husband => "fred", wife => "wilma", daughter => "pebbles" };
2. 산열 을 만 드 는 배열
다음은 해시 배열 을 채 우 는 기술 입 니 다.다음 형식 을 파일 에서 읽 으 려 면:
husband=fred friend=barney
다음 두 순환 중 하 나 를 사용 할 수 있 습 니 다.
while (<>) {
$rec = {};
for $field ( split ) {
($key, $value) = split /=/, $field;
$rec->{$key} = $value;
}
push @AoH, $rec;
}
while (<>) {
push @AoH, { split /[\s=]+/ };
}
키 프로 세 스 getnext_pair 키 / 수 치 를 되 돌려 줍 니 다. 다음 두 순환 중 하 나 를 이용 하여 @ AoH 를 채 울 수 있 습 니 다.
while ( @fields = get_next_pari()) {
push @AoH, {@fields};
}
while (<>) {
push @AoH, { get_next_pair($_) };
}
당신 은 아래 와 같이 기 존의 해시 에 새로운 구성원 을 추가 할 수 있 습 니 다.
$AoH[0]{pet} = "dino";
$AoH[2]{pet} = "santa's little helper";
3. 해시 에 접근 하고 인쇄 하 는 배열
다음 방법 으로 특정한 산열 의 수치 / 키 를 설정 할 수 있 습 니 다.
$AoH[0]{husband} = "fred";
두 번 째 배열 의 남편 (husband) 을 대문자 로 바 꾸 고 하나 로 바 꿔 야 합 니 다.
$AoH[1]{husband} =~ s/(\w)/\u$1/;
당신 은 아래 의 방법 으로 모든 데 이 터 를 인쇄 할 수 있 습 니 다.
for $href ( @AoH ) {
print "{ ";
for $role ( keys %$href ) {
print "$role=$href->{$role} ";
}
print "}
";
}
인용 인쇄
for $i ( 0 .. $#AoH ) {
print "$i is { ";
for $role ( keys %{ $AoH[$i] } ) {
print "$role=$AoH[$i]{$role} ";
}
print "}
";
}
산열
다 차원 의 산열 은 Perl 에서 가장 유연 한 내장 구조 이다.그것 은 마치 하나의 기록 을 연결 하 는 것 처럼 그 기록 자체 에 다른 기록 이 포함 되 어 있다.모든 단계 에서, 당신 은 이 산열 의 색인 을 하나의 문자열 (필요 할 때 발생) 로 만 듭 니 다.단, 해시 에 있 는 키 / 수 치 는 특정한 순서 로 나타 나 지 않 는 다 는 것 을 기억 하 세 요.당신 은 sort 함 수 를 사용 하여 당신 이 좋아 하 는 모든 순서 로 이 짝 을 검색 할 수 있 습 니 다.
1. 산열 을 구성 하 는 산열
다음 방법 으로 익명 산열 의 산열 을 만 들 수 있 습 니 다.
%HoH = (
flintstones => {
husband => "fred",
pal => "barney",
},
jetsons => {
husband => "george",
wife => "jane",
"his boy" => "elroy", #
},
simpsons => {
husband => "homer",
wife => "marge",
kid => "bart",
},
);
% HoH 에 다른 익명 의 해시 태 그 를 추가 하려 면 간단하게 말 할 수 있 습 니 다.
$HoH{ mash } = {
captain => "pierce",
major => "burns",
corporal=> "radar",
}
2 산열 의 산열 생 성
다음은 해시 하 나 를 채 우 는 해시 기법 입 니 다.다음 형식의 파일 에서 데 이 터 를 읽 으 려 면:
flintstones
husband=fred pal=barney wife=wilma pet=dino
다음 두 순환 중 하 나 를 사용 할 수 있 습 니 다.
while( <> ){
next unless s/^(.*?):\S*//;
$who = $1;
for $field ( split ) {
($key, $value) = split /=/, $field;
$HoH{$who}{$key} = $value;
}
}
while( <> ){
next unless s/^(.*?):\S*//;
$who = $1;
$rec = {};
$HoH{$who} = $rec;
for $field ( split ) {
($key, $value) = split /=/, $field;
$rec->{$key} = $value;
}
}
키 프로 세 스 getfamily 키 / 수치 목록 을 되 돌려 줍 니 다. 다음 세 가지 방법 중 하 나 를 가 져 와 서% HoH 를 채 울 수 있 습 니 다.
for $group ("simpsons", "jetsons", "flintstones" ) {
$HoH{$group} = {get_family($group)};
}
for $group ( "simpsons", "jetsons", "flintstones" ) {
@members = get_family($group);
$HoH{$group} = {@menbers};
}
sub hash_families {
my @ret;
for $group (@_) {
push @ret, $group, {get_family($group)};
}
return @ret;
}
%HoH = hash_families( "simpsons", "jetsons", "flintstones" );
당신 은 아래 의 방법 으로 기 존의 해시 에 새로운 구성원 을 추가 할 수 있 습 니 다.
%new_floks = (
wife => "wilma",
pet => "dino",
);
for $what (keys %new_floks) {
$HoH{flintstones}{$what} = $new_floks{$what};
}
3 산열 에 접근 하고 인쇄 하 는 산열
키 / 수 치 를 아래 방법 으로 설정 할 수 있 습 니 다.
$HoH{flintstones}{wife} = "wilma";
어떤 키 글자 / 수 치 를 대문자 로 바 꾸 려 면 이 요소 에 대한 교 체 를 적용 하 십시오.
$HoH{jetsons}{'his boy'} =~ s/(\w)/\u$1/;
당신 은 전후 로 내외 층 의 해시 키 글 자 를 옮 겨 다 니 는 방법 으로 모든 가족 을 인쇄 할 수 있 습 니 다.
for $family ( keys %HoH ) {
print "$family: ";
for $role ( keys %{ $HoH{$family} } ){
print "$role=$person ";
}
print "
";
}
아주 큰 해시 에 서 는 each 를 사용 하여 키 와 수 치 를 동시에 검색 할 수 있 습 니 다. (이렇게 하면 정렬 을 피 할 수 있 습 니 다)
while ( ($family, $roles) = each %HoH ) {
print "$family: ";
while ( ($role, $person) = each %$roles ) {
print "$role=$person";
}
print "
";
}
(나 쁜 것 은, 저장 해 야 할 것 은 그 큰 해시 입 니 다. 그렇지 않 으 면 인쇄 출력 에서 원 하 는 것 을 영원히 찾 을 수 없습니다.) 다음 방법 으로 가족 을 정렬 한 다음 에 발 색 을 정렬 할 수 있 습 니 다.
for $family ( sort keys %HoH ) {
print "$family: ";
for $role ( sort keys %{ $HoH{$family} } ) {
print "$role=$HoH{$family}{$role} ";
}
print "
";
}
가족 번호 에 따라 정렬 해 야 합 니 다 (ASCII 코드 (또는 utf 8 코드). 하나의 스칼라 환경 에서 keys 를 사용 할 수 있 습 니 다.
for $family ( sort { keys %{$HoH{$a} } <=> keys %{$HoH{$b}}} keys %HoH ) {
print "$family: ";
for $role ( sort keys %{ $HoH{$family} } ) {
print "$role=$HoH{$family}{$role};
}
print "
";
}
어떤 고정된 순서 로 한 가족 을 정렬 하려 면 모든 구성원 에 게 하나의 등급 을 부여 하여 실현 할 수 있다.
$i = 0;
for ( qw(husband wife son daughter pal pet) ) { $rank{$_} = ++$i }
for $family ( sort { keys %{$HoH{$a} } <=> keys %{$HoH{$b}}} keys %HoH ) {
print "$family: ";
for $role ( sort { $rank{$a} <=> $rank{$b} } keys %{ $HoH{$family} }) {
print "$role=$HoH{$family}{$role} ";
}
print "
";
}
함수 의 산열
Perl 을 사용 하여 복잡 한 애플 리 케 이 션 이나 인터넷 서 비 스 를 쓸 때 사용자 에 게 많은 명령 을 만들어 서 사용 하도록 해 야 할 수도 있 습 니 다.이러한 프로그램 은 아래 와 같은 코드 로 사용자 의 선택 을 검사 한 다음 에 해당 하 는 동작 을 취 할 수 있 습 니 다.
if ($cmd =~ /^exit$/i) { exit }
elsif ($cmd =~ /^help$/i) { show_help() }
elsif ($cmd =~ /^watch$/i) { $watch = 1 }
elsif ($cmd =~ /^mail$/i) { mail_msg($msg) }
elsif ($cmd =~ /^edit$/i) { $edited++; editmsg($msg); }
elsif ($cmd =~ /^delete$/i) { confirm_kill() }
else {
warn "Unknown command: `$cmd'; Try `help' next time
";
}
또한 데이터 구조 에 지향 함수 의 인용 을 저장 할 수 있 습 니 다. 배열 이나 해시 에 대한 인용 을 저장 할 수 있 는 것 처럼:
%HoF = ( # Compose a hash of functions
exit => sub { exit },
help => \&show_help,
watch => sub { $watch = 1 },
mail => sub { mail_msg($msg) },
edit => sub { $edited++; editmsg($msg); },
delete => \&confirm_kill,
);
if ($HoF{lc $cmd}) { $HoF{lc $cmd}->() } # Call function
else { warn "Unknown command: `$cmd'; Try `help' next time
" }
마지막 두 번 째 줄 에서 우 리 는 성명 의 명령 이름 (소문 자) 이 우리 의 '송환 표'% HoF 에 존재 하 는 지 확인 했다.만약 에 우리 가 응답 하 는 명령 을 호출 하 는 방법 은 해시 값 을 함수 로 하여 인용 을 풀 고 이 함수 에 빈 매개 변수 목록 을 전달 하 는 것 입 니 다.우 리 는 & {$HoF {lc $cmd} () 로 해시 값 을 인용 하거나 Perl 5.6 에서 간단하게 $HoF {lc $cmd} () 일 수 있 습 니 다.
더욱 유연 한 기록
지금까지 우리 가 본 장 에서 본 것 은 모두 간단 하고 두 층 의 동 질 적 인 데이터 구조 이다. 모든 요 소 는 같은 유형의 인용 을 포함 하고 모든 다른 요 소 는 이 층 에 있다.데이터 구 조 는 당연히 그렇지 않 을 수 있다.모든 요 소 는 임의의 형식의 스칼라 를 저장 할 수 있 습 니 다. 이것 은 문자열, 숫자, 또는 모든 것 을 가리 키 는 참조 일 수 있 음 을 의미 합 니 다.이 인용 은 하나의 배열 이나 해시 참조 또는 가짜 해시 또는 이름 이나 익명 함 수 를 가리 키 는 참조 또는 대상 일 수 있 습 니 다.당신 이 할 수 없 는 유일한 일 은 하나의 스칼라 에 여러 개의 인용 물 을 채 우 는 것 입 니 다.만약 당신 이 이런 시 도 를 하고 있다 는 것 을 발견 한다 면, 그것 은 여러 개의 수 치 를 하나 로 압축 하 는 배열 이나 해시 참조 가 필요 하 다 는 것 을 나타 낸다.
다음 절 에서 코드 의 예 를 볼 수 있 습 니 다. 이 코드 들 은 기록 에 저장 하고 싶 은 많은 가능 한 유형의 데 이 터 를 보 여 주 는 것 으로 설계 되 었 습 니 다. 우 리 는 해시 참조 로 이 를 실현 할 것 입 니 다.이 키 글 자 는 모두 대문자 문자열 입 니 다. 이것 은 우리 가 자주 사용 하 는 습관 입 니 다. (가끔 은 이 습관 을 사용 하지 않 지만 우연히 사용 하지 않 습 니 다) 이 해시 가 특정한 기록 형식 으로 사용 된다 면.
1 더욱 유연 한 기록 의 조합, 접근 과 인쇄
다음은 여섯 가지 완전히 다른 도 메 인 을 가 진 기록 입 니 다.
$rec = {
TEXT => $string,
SEQUENCE => [ @old_values ],
LOOKUP => { %some_table },
THATCODE => sub { $_[0] ** $_[1] },
HANDLE => \*STDOUT,
};
TEXT 도 메 인 은 간단 한 문자열 입 니 다.따라서 간단하게 인쇄 할 수 있 습 니 다.
print $rec->{TEXT};
SEQUENCE 와 LOOKUP 는 모두 일반적인 배열 과 해시 참조 입 니 다.
print $rec->{SEQUENCE }[0];
$last = pop @{ $rec->{SEQUENCE} };
print $rec->{LOOKUP}{"key"};
($first_k, $first_v) = each %{ $rec->{LOOKUP} };
THATCODE 는 명명 서브 프로 세 스 이 고 THISCODE 는 익명 서브 프로 세 스 이지 만 호출 은 같 습 니 다.
$that_answer = $rec->{THATCODE}->($arg1, $arg2);
$this_answer = $rec->{THISCODE}->($arg1, $arg2);
여기에 꽃 괄호 를 더 하면 $rec - > {HANDLE} 을 간접 적 인 대상 으로 볼 수 있 습 니 다.
print { $rec->{HANDLE} } "a string
";
하면, 만약, 만약... FileHandle ? 모듈, 이 핸들 을 일반적인 대상 으로 볼 수도 있 습 니 다.
use FileHandle;
$rec->{HANDLE}->autoflush(1);
$rec->{HANDLE}->print("a string
");
2. 더욱 유연 한 기록 의 조합, 방문 과 인쇄
자 연 스 럽 게 당신 의 데이터 구조의 도 메 인 자체 도 임의의 복잡 한 데이터 구조 일 수 있 습 니 다.
%TV = (
flintstones => {
series => "flintstones",
nights => [ "monday", "thursday", "friday" ],
members => [
{ name => "fred", role => "husband", age => 36, },
{ name => "wilma", role => "wife", age => 31, },
{ name => "pebbles", role => "kid", age => 4, },
],
},
jetsons => {
series => "jetsons",
nights => [ "wednesday", "saturday" ],
members => [
{ name => "george", role => "husband", age => 41, },
{ name => "jane", role => "wife", age => 39, },
{ name => "elroy", role => "kid", age => 9, },
],
},
simpsons => {
series => "simpsons",
nights => [ "monday" ],
members => [
{ name => "homer", role => "husband", age => 34, },
{ name => "marge", role => "wife", age => 37, },
{ name => "bart", role => "kid", age => 11, },
],
},
);
3 복잡 기록 산열 의 생 성
Perl 분석 이 복잡 한 데이터 구조 가 상당히 좋 기 때문에 데이터 성명 을 Perl 코드 로 독립 된 파일 에 넣 고 도 나 require 등 내 장 된 함수 로 불 러 올 수 있 습 니 다.또 다른 유행 하 는 방법 은 CPAN 모듈 (예 를 들 어 XML: Parser) 을 사용 하여 다른 언어 (예 를 들 어 XML) 로 표 시 된 임의의 데이터 구 조 를 불 러 오 는 것 이다.
너 는 단편 적 으로 데이터 구 조 를 만 들 수 있다.
$rec = {};
$rec->{series} = "flintstones";
$rec->{nights} = [ find_days()];
파일 에서 읽 어 들 이기 (여기 서 파일 의 형식 이 field = value 문법 이 라 고 가정 합 니 다):
@members = ();
while (<>) {
%fields = split /[\s=]+/;
push @members, {%fields};
}
$rec->{members} = [ @members ];
그 다음 에 하나의 하위 도 메 인 을 키 로 하여 더 큰 데이터 구조 에 쌓 습 니 다.
$TV{ $rec->{series} } = $rec;
데이터 복 사 를 피하 기 위해 서 추가 포인터 도 메 인 을 사용 할 수 있 습 니 다.예 를 들 어 한 사람의 기록 에 'kids' (아이) 데이터 도 메 인 을 포함 해 야 할 수도 있 습 니 다. 이 도 메 인 은 하나의 배열 일 수도 있 습 니 다. 이 배열 은 이 아이 에 게 자신 이 기록 한 인용 을 포함 하고 있 습 니 다.데이터 구조의 일부분 을 다른 부분 으로 가리 키 면 한 곳 에서 데 이 터 를 업데이트 하기 때문에 다른 곳 에서 데 이 터 를 업데이트 하지 않 아 데이터 가 기울 지 않도록 할 수 있 습 니 다.
for $family (keys %TV) {
my $rec = $TV{$family}; #
@kids = ();
for $person ( @{$rec->{members}}) {
if ($person->{role} =~ /kid|son|daughter/) {
push @kids, $person;
}
}
# $rec $TV{$family} !
$rec->{kids} = [@kids];
}
여기 $rec - > {kids} = [@ kids] 할당 복사 배열 내용 입 니 다. 그러나 데 이 터 를 복사 하지 않 고 간단 한 참조 일 뿐 입 니 다.이것 은 만약 당신 이 Bart 에 게 다음 과 같은 나 이 를 부여 한다 면:
$TV{simpsons}{kids}[0]{age}++; # 12 까지 증가
그러면 다음 결 과 를 볼 수 있 습 니 다. $TV {simpsons} {kids} [0] 과 $TV {simpsons} {members} [2] 는 같은 하층 익명 산 목록 을 가리 키 기 때 문 입 니 다.
print $TV{simpsons}{members}[2]{age}; # 인쇄
현재% TV 구 조 를 인쇄 합 니 다:
for $family ( keys %TV ) {
print "the $family";
print " is on ", join (" and ", @{ $TV{$family}{nights} }), "
";
print "its members are:
";
for $who ( @{ $TV{$family}{members} } ) {
print " $who->{name} ($who->{role}), age $who->{age}
";
}
print "children: ";
print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } );
print "
";
}
데이터 구조 저장
나중에 다른 프로그램 에 사용 할 수 있 도록 데이터 구 조 를 저장 하고 싶다 면 사용 할 수 있 는 방법 이 많다.가장 쉬 운 방법 은 Perl 의 Data: Dumper 모듈 을 사용 하 는 것 입 니 다. 데이터 구 조 를 하나의 문자열 로 바 꿀 수 있 습 니 다. 이 문자열 을 프로그램 외부 에 저장 한 다음 에 eval 또는 do 로 다시 구성 할 수 있 습 니 다.
use Data::Dumper;
$Data::Dumper::Purity = 1; # %TV
open (FILE, "> tvinfo.perldata") or die "can't open tvinfo: $!";
print FILE Data::Dumper->Dump([\%TV], ['*TV']);
close FILE or die "can't close tvinfo: $!";
다른 프로그램 (또는 같은 프로그램) 은 나중에 파일 에서 읽 을 수 있 습 니 다.
open (FILE, "< tvinfo.perldata") or die "can't open tvinfo: $!";
undef $/; #
eval ; # %TV
die "can't recreate tv data from tvinfo.perldata: $@" if $@;
close FILE or die "can't close tvinfo: $!";
print $TV{simpsons}{members}[2]{age};
또는 간단 한 것 은:
do "tvinfo.perldata" or die "can't recreate tvinfo: $! $@";
print $TV{simpsons}{members}[2]{age};
그리고 많은 다른 해결 방법 을 사용 할 수 있 습 니 다. 그들의 저장 형식의 범 위 는 포장 의 바 이 너 리 (매우 빠 른) 에서 XML (교환 성 이 매우 좋 음) 까지 입 니 다.다가 오 는 CPAN 미 러 를 확인 해 보 세 요!
문장의 일부 내용 은 【 전송 문 】
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.