배열의 인덱스 가져오기

배열의 인덱스 가져오기

for 루프에서 반복되는 배열의 인덱스를 얻으려고 합니다. 나는 다음과 같은 일을하고있다

arr=( foo bar baz )
for i in $arr; do
  echo "index ${#arr}";
done

그러나 이는 배열의 현재 값 위치가 아니라 배열의 요소 수만 제공합니다. 어떻게 해야 하나요?

답변1

누구도 명확한 답을 갖고 있지 않은 것 같으니 그렇게 하겠습니다.

왜 C나 Java와 같은 주류 언어에서 사용되는 숫자 for 루프를 사용하지 않는 걸까요?

for ((i = 1; i <= $#arr; i++)); do
    echo "Index: $i, value: ${arr[i]}"
done

또는 더 짧을 수도 있습니다(대규모 배열의 경우 더 느리고 잠재적으로 메모리 집약적임).

for i in {1..$#arr}; do
    echo "Index: $i, value: ${arr[i]}"
done

답변2

배열 리터럴 일치와 현재 인덱스를 반환하는 플래그를 사용하여 이를 수행할 수 있습니다.

arr=( foo bar baz )
for i in $arr; do
  echo "index ${arr[(ie)$i]}";
done

i플래그는 인덱스를 반환하며, 이 e플래그는 i문자 그대로 문자열과 일치하도록 동작을 수정합니다. 표현식은 다음과 같습니다. for arr은 문자열 $i와 일치하고 문자 그대로 인덱스를 반환합니다. 이 방법의 단점은 배열의 모든 요소가 고유한 경우에만 신뢰할 수 있다는 것입니다. 그렇지 않으면 일종의 카운터를 사용해야 합니다.

답변3

zsh 5.0.6부터 배열을 확장하고 압축을 통해 인덱스를 생성할 수 있습니다.

for k v in "${(@)${=${(eQ):-'$( (( $#ary )) && echo {1..$#ary})'}}:^ary}"; do
  [[ -z $k ]] && continue
  echo "index: $k - value: $v"
done

나는 실제로 그것을 사용하지 않을 것이며 (미래에 칼에 찔릴 것을 두려워하여) 많은 수의 요소가 있는 배열의 경우 속도가 느려질 것입니다. zsh의 배열은 희박할 수 없으므로 카운터를 늘리는 것이 더 효율적입니다.

답변4

"실용적인" 동등(설명의 제한 사항 참조)이지만 llua가 수행하는 대부분의 작업을 수행하는 더 간단한 방법은 붙여넣기와 절차적 대체를 사용합니다.

arr=( foo "bar 't' ttt" baz )
paste <(echo {1..$#arr}"\n") <(echo ${^arr}"\n") | head -n -1 | while read i v; do
  echo index $i, val : $v;
done

편집: 이것은 이전 버전의 zsh에서 작동하며 공백과 따옴표를 처리합니다. (글쎄요, for를 사용하지 않지만 작업에 "for 루프" 대신 "반복"이라고 표시됩니다.

arr=( foo "bar 't' ttt" baz )
paste <(echo {1..$#arr}"\n") <(echo ${^arr}"\n") | head -n -1 | while read i v; do
  echo index $i, val : $v;
done

관련 정보