Perl에서 배열의 크기를 구합니다


243

배열의 크기를 찾는 여러 가지 방법을 찾은 것 같습니다. 이 세 가지 방법의 차이점은 무엇입니까?

my @arr = (2);
print scalar @arr; # First way to print array size

print $#arr; # Second way to print array size

my $arrSize = @arr;
print $arrSize; # Third way to print array size

13
다른 방법 : print 0+@arr, print "".@arr,print ~~@arr
폭도

3
@mob, 험, 하나는 방지 할 수 있습니다 "".@arr"@arr"상당히 다른 무언가를.
ikegami

39
"두 번째 방법"은 배열 크기를 인쇄하는 방법이 아닙니다 ...
tadmc

스칼라 컨텍스트에서; @arr은 테이블 크기를 반환합니다. $ x = @ arr은 스칼라 컨텍스트입니다. $ # arr는 배열의 마지막 인덱스를 반환합니다. 0부터 시작하여 인덱싱하는 것은 $ # arr + 1 == @arr입니다. 예를 들어 $ arr [100] = 'any'와 같이 일부 요소를 순서대로 쓰지 않으면 테이블이 자동으로 최대 인덱스 100으로 증가하고 인덱스 0을 포함하여 101 개의 요소로 증가합니다.
Znik

답변:


234

첫 번째와 세 번째 방법은 동일합니다. 스칼라 컨텍스트에서 배열을 평가합니다. 이것을 배열의 크기를 얻는 표준 방법이라고 생각합니다.

두 번째 방법은 실제로 배열의 마지막 인덱스를 반환하는데, 이는 일반적으로 배열 크기와 동일하지 않습니다.


29
(1,2,3)의 크기는 3이고 인덱스는 기본적으로 0, 1 및 2입니다. 따라서이 경우 $ # arr는 3이 아닌 2가됩니다.
Nate CK

5
사전 정의 된 변수는 $["배열에서 첫 번째 요소의 색인 및 하위 문자열의 첫 번째 문자의 색인"( perldoc perlvar)을 지정합니다. 기본적으로 0으로 설정되어 있으며 0 이외의 값으로 설정하는 것은 권장하지 않습니다.
Keith Thompson

5
@Keith Thompson $[은 낙담했습니다 (10 년이 지났습니다). $[더 이상 사용되지 않습니다. $[경고를 사용 하지 않는 경우에도 사용 중단 경고가 표시됩니다. $[5.16에서 0 이외의 값을 할당 하면 오류가 발생합니다. 우리는 $[이미 언급을 멈출 수 있습니까 ?
ikegami

2
실제로 5.14보다 오래된 @Keith Thompson. 그러나 내가 말했듯이, 그것은 그보다 훨씬 오랫동안 낙담하고 더 이상 사용되지 않으며, 누군가 $[가 그 효과를 알고있을 것입니다.
ikegami

7
@ikegami : 예,하지만 사람 사이의 차이를 이해하려고 노력 scalar @arr하고 $#arr해야 여전히 의 가능한 효과 이해 $[가 비록 희귀을.
Keith Thompson

41

첫째, 두 번째는 다른 두 가지와 동일하지 않습니다. $#array배열의 마지막 인덱스를 반환합니다. 배열의 크기보다 1이 작습니다.

다른 두 개는 사실상 동일합니다. 스칼라 컨텍스트를 만들기 위해 단순히 두 가지 방법을 사용하고 있습니다. 가독성 문제로 귀결됩니다.

나는 개인적으로 다음을 선호합니다.

say 0+@array;          # Represent @array as a number

나는 그것을보다 명확하게 발견

say scalar(@array);    # Represent @array as a scalar

my $size = @array;
say $size;

후자는 이것처럼 매우 분명해 보이지만 다른 코드의 일부 인 경우 여분의 줄이 선명도에서 벗어납니다. @array스칼라 컨텍스트에서 수행 하는 작업을 가르치 $size거나 두 번 이상 사용하려는 경우 유용합니다 .


15
개인적으로 나는 "스칼라"키워드를 사용하는 버전을 선호합니다. 왜냐하면 그것은 스칼라 컨텍스트를 강요한다는 것이 명백하기 때문입니다. my $size=@array잘못된시길을 사용한 경우 실수 일 수 있습니다.
Nate CK

5
정말 나쁜 생각입니다. scalar아무 이유없이 사용 하는 사람들 은 잘못된 교훈을 배웁니다. 그들은 조작자가 스칼라로 강제 변환 할 수있는리스트를 리턴하도록 머리에 들어가기 시작합니다. 수십 번 보았습니다.
ikegami

2
왜 이것이 "이유가 없습니까?" scalar목록을 스칼라 컨텍스트로 강제 변환하기 때문에 사용 중입니다. 그것이 그것을 사용해야하는 올바른 이유입니다. 귀하의 예제는 정확히 같은 일을 수행하지만 암시 적으로 스칼라 컨텍스트에서 목록 변수를 평가할 때 Perl의 기능에 의존합니다. 따라서 귀하의 예에서는 독자가 해당 컨텍스트에서 Perl의 내재 된 동작에 대해 알아야합니다. 식에 암시 적 동작 계층을 하나 더 추가하는 것만으로 Perl은 이미 프로그램을 해독하기 위해 추론해야 할 암시 적 동작이 너무 많습니다.
Nate CK

2
@Nate CK, Re "이 이유가없는 이유는 무엇입니까? scalar목록을 스칼라 컨텍스트로 강제 변환하기 때문에 사용 하고 있습니다", 잘못된 교훈을 배우는 것에 대한 나의 요점을 증명했습니다. 이것은 완전히 거짓입니다. 에 의해 강제 된 목록이 없습니다 scalar. (가 않았다 경우 scalar(@array)scalar(@array[0..$#array])같은 일을 반환합니다.) scalar(@array)알려줍니다 @array당신이 이미와 함께 할 그에게 스칼라를 반환 my $size=.
ikegami

2
믿거 나 말거나 개발자는 다른 개발자가 작성한 코드를 디버깅해야합니다. 그리고 개발자는 3 년 전에 작성한 코드를 디버깅해야합니다.
네이트 CK

27

이것은 배열을 스칼라 컨텍스트로 만들어서 크기를 계산하여 크기를 얻습니다.

print scalar @arr;

이것은 스칼라 변수에 할당되기 때문에 배열을 스칼라 컨텍스트로 만드는 또 다른 방법입니다.

my $arrSize = @arr;

이것은 배열에서 마지막 요소의 색인을 얻습니다. 실제로 크기에서 1을 뺀 값입니다 (색인이 0에서 시작한다고 가정하면 펄에서 조정할 수 있지만 일반적으로 나쁜 생각입니다).

print $#arr;

이 마지막 것은 배열 크기를 얻는 데 사용하기에 좋지 않습니다. 배열의 마지막 요소를 얻으려는 경우 유용합니다.

my $lastElement = $arr[$#arr];

또한 스택 오버플로에서 볼 수 있듯이이 구문은 대부분의 구문 강조 표시기에서 올바르게 처리되지 않습니다 ...


2
참고 사항 : $arr[-1]마지막 요소를 얻는 데 사용 하십시오. 그리고 $arr[-2]두 번째 사람을 얻는 것입니다.
tuomassalo

1
@ tuomassalo : 귀하의 제안이 더 나은 접근법이라는 데 동의합니다. 돌이켜 보면 $#arr매우 유용한 기능은 아니며 다른 언어에없는 것도 우연이 아닙니다.
네이트 CK

6

두 번째 방법을 사용하려면 1을 추가하십시오.

print $#arr + 1; # Second way to print array size

for [0..$#array] { print $array[$_ ] } 요소 수를 얻는 목적이 배열을 반복하는 것이라면 실제로 잘 작동합니다. 장점은 정렬 된 카운터뿐만 아니라 요소를 얻는 것입니다.
Westrock

5

두 번째를 약간 수정하면 세 가지 모두 동일한 결과를 제공합니다.

my @arr = (2, 4, 8, 10);

print "First result:\n";
print scalar @arr; 

print "\n\nSecond result:\n";
print $#arr + 1; # Shift numeration with +1 as it shows last index that starts with 0.

print "\n\nThird result:\n";
my $arrSize = @arr;
print $arrSize;

5
이미 언급 된 내용에서이 아무것도 다른 대답과 하나?
devnull

5

예:

my @a = (undef, undef);
my $size = @a;

warn "Size: " . $#a;   # Size: 1. It's not the size
warn "Size: " . $size; # Size: 2

2

"펄 변수 유형"섹션perlintro 설명서 포함

특수 변수 $#array는 배열의 마지막 요소의 인덱스를 알려줍니다.

print $mixed[$#mixed];       # last element, prints 1.23

$#array + 1배열에 몇 개의 항목이 있는지 알려 주려고 할 수 있습니다 . 귀찮게하지 마십시오. 이와 같이 @arrayPerl이 스칼라 값을 찾을 것으로 예상되는 위치 ( "스칼라 컨텍스트에서")를 사용하면 배열의 요소 수를 얻을 수 있습니다.

if (@animals < 5) { ... }

perldata 문서는 또한이를 커버 "스칼라 값"섹션 .

스칼라 컨텍스트에서 배열을 평가하면 배열의 길이가 반환됩니다. C 쉼표 연산자와 같이 마지막 값을 반환하는 목록이나 반환하려는 느낌을 반환하는 내장 함수는 목록에 해당되지 않습니다. 다음은 항상 사실입니다.

scalar(@whatever) == $#whatever + 1;

일부 프로그래머는 의심 할 여지가 없도록 명시 적 변환을 사용하도록 선택합니다.

$element_count = scalar(@whatever);

같은 섹션의 앞부분에서 배열의 마지막 요소의 인덱스를 얻는 방법을 설명합니다.

배열의 길이는 스칼라 값입니다. 에서처럼을 @days평가 하여 배열의 길이를 찾을 수 있습니다 . 그러나 이것은 배열의 길이가 아닙니다. 마지막 요소의 첨자이며 일반적으로 0 번째 요소가 있기 때문에 다른 값입니다.$#dayscsh


2

배열 크기를 인쇄하는 방법에는 여러 가지가 있습니다. 다음은 모두의 의미입니다. 배열이my @arr = (3,4);

방법 1 : 스칼라

이것은 배열의 크기를 얻는 올바른 방법입니다.

print scalar @arr;  # prints size, here 2

방법 2 : 색인 번호

$#arr배열의 마지막 인덱스를 제공합니다. 따라서 배열의 크기가 10이면 마지막 인덱스는 9입니다.

print $#arr;     # prints 1, as last index is 1
print $#arr + 1; # Add 1 to last index to get array size

여기서는 배열을 0-indexed 로 간주하여 1을 추가 합니다. 그러나 0이 아닌 경우이 논리는 실패 합니다.

perl -le 'local $[ = 4; my @arr=(3,4); print $#arr + 1;'   # prints 6

위의 예는 초기 인덱스를 4로 설정했기 때문에 6을 인쇄합니다. 이제 인덱스는 요소 3과 4를 가진 5와 6입니다.

방법 3 :

스칼라 컨텍스트에서 배열을 사용하면 배열의 크기를 반환합니다.

my $size = @arr;
print $size;   # prints size, here 2

실제로 방법 3과 방법 1은 동일합니다.


2

perldoc perldata 에서 인용하는 것이 안전해야합니다.

다음은 항상 사실입니다.

scalar(@whatever) == $#whatever + 1;

당신이 $ # whatever ++를하지 않고 크기 나 배열을 신비롭게 늘리는 한.

배열 인덱스는 0으로 시작합니다.

null 목록 ()을 할당하여 배열을 무단으로자를 수 있습니다. 다음은 동일합니다.

    @whatever = ();
    $#whatever = -1;

배열을 비우는 방법을 찾는 방법은 무엇입니까? $ # empty == -1이면 찾았습니다.


1

int(@array)스칼라라는 주장을 위협하기 때문에 어떨까요?


0

배열의 크기를 찾으려면 scalar키워드를 사용하십시오 .

print scalar @array;

배열의 마지막 색인을 찾으려면 $#(Perl 기본 변수)가 있습니다. 배열의 마지막 인덱스를 제공합니다. 배열이 0에서 시작하면 다음에 하나를 추가하여 배열의 크기를 얻습니다 $#.

print "$#array+1";

예:

my @a = qw(1 3 5);
print scalar @a, "\n";
print $#a+1, "\n";

산출:

3

3
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.