배열

배열 에서 R

1개의 연습 문제

배열 소개

R의 list는 순서가 있는 항목들의 모음이고, vectors와는 몇 가지 점에서 달라요:

  • 항목들이 서로 다른 타입일 수 있어요(예를 들어 numeric과 character를 섞을 수 있어요).
  • 항목이 복잡한 구조일 수도 있어요(예를 들어 벡터, 다른 list 등).
  • 요소에 접근하는 문법도 조금 달라요.

다른 언어에 빗대는 것은 정확하지 않아요. R의 list는 Python 딕셔너리와 어느 정도 비슷하지만, list는 순서가 있고 숫자 인덱스로 접근할 수 있어요. C의 struct와도 어느 정도 비슷한데, list는 실행 중에 얼마든지 확장할 수 있다는 점이 달라요.

list 만들기

요소에 이름을 붙이는 일은(흔히 "태그"라고 불러요) 벡터보다 list에서 더 흔해요:

list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3

#> $y
#> [1] 4.2

#> $color
#> [1] "blue"

하지만 태그는 선택 사항이라, 붙이지 않으면 R이 그냥 인덱스 번호를 사용해요:

list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3

#> [[2]]
#> [1] 4.2

#> [[3]]
#> [1] "blue"

list의 요소에 접근하기

방법은 세 가지이고, 각각 다른 상황에서 유용해요.

1. $tag 표기법

태그 이름을 미리 알고 있을 때 아주 흔히 써요.

point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"

2. [[tag]] 표기법

태그 이름을 실행 중에 정할 수 있다는 장점이 있어요. 대괄호가 두 개라는 점에 주목해요.

want <- "y"
point[[want]] # same as point$y
#> [1] 4.2

3. 위치 인덱스 사용하기

list에 태그가 있든 없든 이 방법은 통해요. 여기서도 대괄호는 두 개예요.

point[[3]] # same as point$color
#> [1] "blue"

요소 추가와 삭제

간단해요. 요소에 값을 할당하면, 이미 있으면 수정되고 없으면 새로 추가돼요.

point$color <- "red"
point$trust <- TRUE

# str() gives more compact output than the default display
str(point) 
#> List of 4
#>  $ x    : num 5.3
#>  $ y    : num 4.2
#>  $ color: chr "red"
#>  $ trust: logi TRUE

삭제하려면 필요 없는 요소에 NULL을 할당해요.

point$trust <- NULL
str(point)  
#> List of 3
#>  $ x    : num 5.3
#>  $ y    : num 4.2
#>  $ color: chr "red"

list는 "재귀 벡터"예요

vector 클래스는 기술적으로는 atomic vector라고 불러요. 원자적 값, 즉 numeric, character, boolean 등만 담을 수 있기 때문이에요. list는 다른 list를 담을 수 있어서 recursive vector라고도 해요.

이건 단순히 이름을 붙이는 기술적인 이야기를 넘어, list가 얼마든지 복잡한 구조를 가질 수 있다는 점을 알려줘요. list의 요소에 접근할 때 무엇이 나올지는 프로그래머가 직접 이해하고 있어야 해요.

list 인덱싱 더 알아보기

위의 몇몇 예제에서는 list의 요소에 접근할 때 이중 대괄호 [[ ]]를 썼어요. 이 방법은 요소를 원래의 타입으로 펼치려고 하는데, 숫자나 문자열 하나만 필요할 때 유용해요.

홑 대괄호 [ ]를 쓰면 이런 펼침이 일어나지 않고, 반환되는 값은 하위 list가 돼요.

point[["color"]]
#> [1] "red"  # flattened

point["color"]
#> $color
#> [1] "red"  # sublist

하위 list가 R을 처음 배우는 사람에게 필요한 형태가 아닐 때도 있지만, 어쨌든 이 점은 알아 두세요. 유연성을 최대한 살리기 위해, 많은 R 표준 함수는 여기처럼 원자적 값 하나만 담고 있을 때도 list를 반환해요.

벡터로 바꾸는 방법은 두 가지가 있어요.

  1. [[1]]로 첫 번째 요소를 가져와요.
  2. unlist() 함수를 사용해요.
pt <-point["color"]

pt[[1]]
#> [1] "red" # simple 1-element vector

unlist(pt)
#> color 
#> "red"  # 1-element vector with name

unlist()는 조심해서 써요. 이렇게 단순한 경우에는 구조를 펼치는 게 유용하지만, list 요소가 복잡해지면 예상치 못한 결과가 나올 수 있어요.

Advanced

내부 표현

list는 원자적 vector와 마찬가지로 메모리에 연속해서 저장돼요. 차이는 숫자형 벡터와 불리언 벡터는 값을 저장하지만, list는 메모리 다른 곳에 있는 객체에 대한 참조를 저장한다는 점이에요.

R을 쓰는 사람에게는 이 사실이 그다지 중요하지 않지만, Exercism처럼 여러 언어를 다루는 커뮤니티에서는 다른 언어에 익숙한 프로그래머에게 도움이 될 수 있어요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요

배열 배우기