문제

지도 기능의 요점을 실제로 이해하지 못하고 있습니다.누구든지 예를 들어 사용법을 설명할 수 있나요?

루프 대신 이것을 사용하면 성능상의 이점이 있습니까? 아니면 단지 설탕입니까?

도움이 되었습니까?

해결책

다른 목록을 기반으로 목록을 생성 할 때마다

# Double all elements of a list
my @double = map { $_ * 2 } (1,2,3,4,5);
# @double = (2,4,6,8,10);

목록은 특정 속성을 기반으로 객체의 해시 테이블을 원한다면 목록이 쉽게 해시로 변환되므로 다음과 같습니다.

# @user_objects is a list of objects having a unique_id() method
my %users = map { $_->unique_id() => $_ } @user_objects;
# %users = ( $id => $obj, $id => $obj, ...);

정말 일반적인 도구입니다. 응용 프로그램에서 잘 사용하기 위해 사용하기 시작해야합니다.

일부는 가독성 목적으로 장점 루핑 코드를 선호 할 수도 있지만 개인적으로는 map 더 읽기 쉬운.

다른 팁

우선, 배열을 변환하는 간단한 방법입니다.

my @raw_values = (...);
my @derived_values;
for my $value (@raw_values) {
    push (@derived_values, _derived_value($value));
}

당신은 말할 수 있습니다

my @raw_values = (...);
my @derived_values = map { _derived_value($_) } @raw_values;

또한 빠른 조회 테이블을 구축하는 데 유용합니다.

my $sentence = "...";
my @stopwords = (...);
my @foundstopwords;
for my $word (split(/\s+/, $sentence)) {
    for my $stopword (@stopwords) {
       if ($word eq $stopword) {
           push (@foundstopwords, $word);
       }
    }
}

넌 말할 수있다

my $sentence = "...";
my @stopwords = (...);
my %is_stopword = map { $_ => 1 } @stopwords;
my @foundstopwords = grep { $is_stopword{$_} } split(/\s+/, $sentence);

한 목록을 다른 목록으로부터 도출하려는 경우에도 유용하지만 특히 임시 변수가 장소를 혼란스럽게 할 필요는 없습니다.

my %params = ( username => '...', password => '...', action => $action );
my @parampairs;
for my $param (keys %params) {
    push (@parampairs, $param . '=' . CGI::escape($params{$param}));
}
my $url = $ENV{SCRIPT_NAME} . '?' . join('&', @parampairs);

당신은 훨씬 더 단순하다고 말합니다

my %params = ( username => '...', password => '...', action => $action );
my $url = $ENV{SCRIPT_NAME} . '?'
    . join('&', map { $_ . '=' . CGI::escape($params{$_}) } keys %params);

(편집 : 마지막 줄에서 누락 된 "키 %매개 변수"를 수정했습니다)

그만큼 map 함수는 목록을 변환하는 데 사용됩니다. 기본적으로 특정 유형의 교체를위한 구문 설탕입니다. for[each] 루프. 일단 머리를 감싸면 어디에서나 용도로 사용됩니다.

my @uppercase = map { uc } @lowercase;
my @hex       = map { sprintf "0x%x", $_ } @decimal;
my %hash      = map { $_ => 1 } @array;
sub join_csv { join(',', map {'"' . $_ . '"' } @_ }

참조 Schwartzian 변환 MAP의 고급 사용.

조회 해시를 만드는데도 편리합니다.

my %is_boolean = map { $_ => 1 } qw(true false);

동일합니다

my %is_boolean = ( true => 1, false => 1 );

저축은 많지 않지만 정의하고 싶다고 가정합니다. %is_US_state?

지도 다른 목록의 요소를 변환하여 목록을 만드는 데 사용됩니다.

grep 다른 목록의 요소를 필터링하여 목록을 만드는 데 사용됩니다.

종류 다른 목록의 요소를 정렬하여 목록을 만드는 데 사용됩니다.

이러한 각 연산자는 목록의 요소를 변환, 필터링 또는 비교하는 데 사용되는 코드 블록(또는 표현식)을 받습니다.

을 위한 지도, 블록의 결과는 새 목록의 하나 이상의 요소가 됩니다.현재 요소의 별칭은 $_입니다.

을 위한 grep, 블록의 부울 결과는 원래 목록의 요소가 새 목록에 복사되는지 여부를 결정합니다.현재 요소의 별칭은 $_입니다.

을 위한 종류, 블록은 두 개의 요소($a 및 $b로 별칭)를 수신하고 $a가 $b보다 크거나 같거나 작은지를 나타내는 -1, 0 또는 1 중 하나를 반환할 것으로 예상됩니다.

그만큼 슈바르츠 변환 이러한 연산자를 사용하여 목록 정렬에 사용할 값(속성)을 효율적으로 캐시합니다. 특히 이러한 속성을 계산할 때 비용이 적지 않게 발생합니다.

이는 원래 요소와 정렬하려는 계산된 값을 요소 배열 참조로 포함하는 중간 배열을 생성하여 작동합니다.이 배열은 이미 계산된 값을 비교하여 다른 중간 배열(이 배열은 정렬됨)을 생성하는 sort로 전달되며, 이는 다시 캐시된 값을 버리는 다른 맵으로 전달되어 배열을 초기 목록 요소로 복원합니다(그러나 이제 원하는 순서대로).

예(마지막 수정 시간을 기준으로 정렬하여 현재 디렉터리에 파일 목록을 만듭니다):

@file_list = glob('*');
@file_modify_times = map { [ $_, (stat($_))[8] ] } @file_list;
@files_sorted_by_mtime = sort { $a->[1] <=> $b->[1] } @file_modify_times;
@sorted_files = map { $_->[0] } @files_sorted_by_mtime;

연산자를 함께 연결하면 중간 배열에 대한 변수 선언이 필요하지 않습니다.

@sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, (stat($_))[8] ] } glob('*');

다음을 삽입하여 정렬하기 전에 목록을 필터링할 수도 있습니다. grep (동일한 캐시된 값을 필터링하려는 경우):

예(지난 24시간 동안 수정된 파일 목록을 마지막 수정 시간으로 정렬):

    @sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } grep { $_->[1] > (time - 24 * 3600 } map { [ $_, (stat($_))[8] ] } glob('*');

맵 함수는 목록의 각 요소에 대한 표현식을 실행하고 목록 결과를 반환합니다. 다음 목록이 있다고 가정 해 봅시다

@names = ("andrew", "bob", "carol" );

그리고 나는이 이름들 각각의 첫 글자를 대문자로 만들고 싶었습니다. 나는 그들을 통과하고 각 요소의 ucfirst에 전화 할 수 있거나 다음을 수행 할 수 있습니다.

@names = map (ucfirst, @names);

맵 함수는 함수형 프로그래밍 패러다임의 아이디어입니다.함수형 프로그래밍에서 함수는 일급 객체입니다. 즉, 다른 함수에 인수로 전달될 수 있습니다.Map은 간단하지만 이에 대한 매우 유용한 예입니다.인수로 함수를 사용합니다. f) 및 목록 l. f 하나의 인수를 취하는 함수여야 하며, map은 단순히 적용됩니다. f 목록의 모든 요소에 l. f 모든 요소에 필요한 모든 작업을 수행할 수 있습니다.모든 요소에 하나를 추가하고, 모든 요소를 ​​제곱하고, 모든 요소를 ​​데이터베이스에 쓰거나, 모든 요소에 대해 웹 브라우저 창을 엽니다. 이는 유효한 URL입니다.

사용의 장점 map 목록의 요소에 대한 반복을 훌륭하게 캡슐화한다는 것입니다.당신이 해야 할 일은 "하라"라고 말하는 것뿐이다. f 모든 요소에 적용되며, 이는 map 최선의 방법을 결정하기 위해.예를 들어 map 작업을 여러 스레드로 분할하도록 구현될 수 있으며 호출자에게 완전히 투명합니다.

참고하세요 map Perl에만 국한된 것은 아닙니다.이는 기능적 언어에서 사용되는 표준 기술입니다.함수 포인터를 사용하여 C에서 구현하거나 "함수 개체"를 사용하여 C++에서 구현할 수도 있습니다.

"그냥 설탕"은 가혹합니다. 루프는 설탕 일뿐입니다. 만약다면 루프 구조물이 모든 것을 할 수 있습니다.

MAP는 충분한 수준의 기능으로, 머리에 훨씬 더 복잡한 작업을 유지하는 데 도움이되므로 더 큰 문제를 코딩하고 디버그 할 수 있습니다.

Hall & Schwartz의 "효과적인 Perl 프로그래밍"을 역설하려면지도를 남용 할 수 있지만 기존 목록에서 새 목록을 만드는 데 가장 적합한 것으로 생각합니다.

3,2의 제곱 목록을 만들고 & 1 :

@numbers = (3,2,1);
@squares = map { $_ ** 2 } @numbers;

비밀번호 생성 :

$ perl -E'say map {chr(32 + 95 * rand)} 1..16'
# -> j'k=$^o7\l'yi28G

맵을 사용하여 목록을 변환하고 결과를 다른 목록에 할당하고 Grep을 목록을 필터링하고 결과를 다른 목록에 할당합니다. "기타"목록은 변환/필터링하는 목록과 동일한 변수 일 수 있습니다.

my @array = ( 1..5 );
@array = map { $_+5 } @array;
print "@array\n";
@array = grep { $_ < 7 } @array;
print "@array\n";

기존 목록에서 새 목록을 만들고 싶을 때마다 사용됩니다.

예를 들어 문자열 목록에 구문 분석 기능을 매핑하여 정수로 변환 할 수 있습니다.

목록을 An으로 변환 할 수 있습니다 표현 안에있는 것보다 진술. 그렇게 정의 된 병사들의 해시를 상상해보십시오.

{ name          => 'John Smith'
, rank          => 'Lieutenant'
, serial_number => '382-293937-20'
};

그런 다음 이름 목록에서 별도로 작동 할 수 있습니다.

예를 들어,

map { $_->{name} } values %soldiers

이다 표현. 표현이 허용되는 곳이면 어디든 갈 수 있습니다. 할당 할 수 없습니다.

${[ sort map { $_->{name} } values %soldiers ]}[-1]

최대를 취하는 배열을 색인화합니다.

my %soldiers_by_sn = map { $->{serial_number} => $_ } values %soldiers;

운영 표현의 장점 중 하나는 임시 변수에서 나오는 버그를 줄이는 것입니다.

McCoy 씨가 고려할 모든 Hatfields를 필터링하려면 최소한의 코딩으로 해당 확인을 추가 할 수 있습니다.

my %soldiers_by_sn 
    = map  { $->{serial_number}, $_ } 
      grep { $_->{name} !~ m/Hatfield$/ } 
      values %soldiers
      ;

이 데이터와의 상호 작용이 특정 목적을 위해 깊은 곳에 도달해야한다면 더 많은 일을 할 것이라고 척하는 많은 코드를 작성할 필요가 없습니다.

다른 사람들이 말했듯이 Map은 목록에서 목록을 만듭니다. 한 목록의 내용을 다른 목록에 "매핑"하는 것을 생각하십시오. 다음은 CGI 프로그램의 일부 코드가 특허 번호 목록을 가져 와서 특허 애플리케이션에 하이퍼 링크를 인쇄합니다.

my @patents = ('7,120,721', '6,809,505', '7,194,673');
print join(", ", map { "<a href=\"http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL&p=1&u=/netahtml/srchnum.htm&r=0&f=S&l=50&TERM1=$_\">$_</a>" } @patents);

다른 사람들이 말했듯이,지도는 목록을 변환하는 데 가장 유용합니다. 언급되지 않은 것은 맵과 루프의 "동등한"차이입니다.

한 가지 차이점은 반복되는 목록을 수정하는 표현식에 적합하지 않다는 것입니다. 이 중 하나는 종료되고 다른 하나는 다음과 같습니다.

perl -e '@x=("x"); map { push @x, $_ } @x'
perl -e '@x=("x"); push @x, $_ for @x'

또 다른 작은 차이점은 문맥 맵 블록 내부에는 목록 컨텍스트가 있지만 For Loop은 무효 컨텍스트를 제공합니다.

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