간단한 배경 : 널리 사용되는 많은 (대부분의) 현대 프로그래밍 언어에는 적어도 몇 개의 ADT (추상 데이터 유형)가 공통적으로 있습니다.
문자열 (문자로 구성된 시퀀스)
목록 (정렬 된 값 모음) 및
지도 기반 유형 (키를 값에 매핑하는 정렬되지 않은 배열)
R 프로그래밍 언어에서 처음 두 개는 각각 character
및 로 구현됩니다 vector
.
R을 배우기 시작했을 때, 거의 처음부터 두 가지가 명백 list
했습니다 .R에서 가장 중요한 데이터 유형입니다 (R의 부모 클래스이기 때문에 data.frame
). 그리고 두 번째로, 그들이 어떻게 작동했는지 이해할 수 없었습니다. 내 코드에서 올바르게 사용하기에 충분하지 않습니다.
우선 R의 list
데이터 유형은 맵 ADT ( dictionary
Python, NSMutableDictionary
Objective C, hash
Perl 및 Ruby, object literal
Javascript 등)를 간단하게 구현 한 것 같습니다 .
예를 들어, 키-값 쌍을 생성자 (Python의 경우는 dict
아님 list
) 에 전달하여 Python 사전과 같이 생성합니다 .
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
그리고 파이썬 사전과 같이 R List의 항목에 액세스합니다 (예 :) x['ev1']
. 마찬가지로 다음과 같이 '키' 또는 '값' 만 검색 할 수 있습니다 .
names(x) # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"
unlist(x) # fetch just the 'values' of an R list
# ev1 ev2 rv
# "10" "15" "Group 1"
x = list("a"=6, "b"=9, "c"=3)
sum(unlist(x))
# [1] 18
그러나 R list
은 다른지도 유형의 ADT 와 다릅니다 (어쨌든 내가 배운 언어 중에서). 내 생각에 이것은 S의 초기 사양, 즉 기초부터 데이터 / 통계 DSL (도메인 특정 언어)을 설계하려는 의도의 결과라고 생각합니다.
list
널리 사용되는 다른 언어 (예 : Python, Perl, JavaScript)에서 R 과 매핑 유형의 세 가지 중요한 차이점 :
먼저 , list
R에서 S는이다 정렬 막 벡터처럼 그 값을 키가되는 경우에도 (즉, 키는 임의의 해쉬 값이 아닌 정수 순차적 일 수있다), 수집. 거의 항상 다른 언어의 매핑 데이터 형식이 정렬되지 않았습니다 .
둘째 , list
S는 당신이 전달되지 않습니다에도 불구하고 기능에서 반환 할 수 있습니다 list
당신이 함수를 호출 할 때, 그리고 비록 (가) 반환 된 기능 list
(명시 적)이 포함되어 있지 않습니다 list
물론 (생성자, 당신에 의해 실제로이 처리 할 수 을 호출하여 반환 된 결과를 래핑 unlist
:
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x) # returns 'list', not a vector of length 2
# [1] list
세 번째 R의의 독특한 기능 list
들 : 그들이 다른 ADT의 구성원이 될 수 있다는 것을하지 않는 것, 당신이 그렇게하려고하면 다음 기본 컨테이너는 강제 변환됩니다 list
. 예 :
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
여기에서의 나의 의도는 언어를 비판하거나 언어를 문서화하는 방법이 아니다. 마찬가지로 list
데이터 구조 또는 작동 방식에 문제가 있음을 제안하지 않습니다 . 내가 추구하는 것은 그것들이 어떻게 작동하는지에 대한 나의 이해로 코드에서 올바르게 사용할 수 있습니다.
내가 더 잘 이해하고 싶은 종류는 다음과 같습니다.
함수 호출이 언제
list
(예 :strsplit
위에서 언급 한 표현)을 반환 할 것인지를 결정하는 규칙은 무엇입니까 ?명시 적으로 이름을
list
(예 :)에 할당하지 않으면list(10,20,30,40)
기본 이름은 1로 시작하는 순차 정수입니까? (그렇지 않으면 우리는 이러한 유형의 강요 할 수없는 것, 내가 생각,하지만 난 대답은 '예'확신에서 멀리이다list
w /로 전화 벡터에unlist
.)이 두 개의 다른 연산자 인
[]
, 및 왜 같은 결과를[[]]
반환 합니까?x = list(1, 2, 3, 4)
두 표현식 모두 "1"을 반환합니다.
x[1]
x[[1]]
왜이 두 표현식 이 같은 결과를 반환 하지 않습니까?
x = list(1, 2, 3, 4)
x2 = list(1:4)
R 문서 ( ?list
, R-intro
) 를 가리 키지 마십시오. 필자는이 내용을주의 깊게 읽었으며 위에서 언급 한 유형의 질문에 대답하는 데 도움이되지 않습니다.
(마지막으로, 최근 에 S4 클래스를 통해 일반적인 맵 유형 동작 hash
을 구현 하는 R 패키지 (CRAN에서 사용 가능)를 배우고 사용하기 시작했습니다 .이 패키지를 확실히 추천 할 수 있습니다.)
list
R의 해시와는 다른 방법으로 귀하의 목록을 확장하는 사람 은 없었습니다. 주목할만한 것이 하나 더 있습니다. list
R에서 동일한 참조 이름을 가진 두 개의 멤버를 가질 수 있습니다. 이것이 obj <- c(list(a=1),list(a=2))
유효하고 이름이 'a'인 두 개의 값이있는 목록을 리턴한다고 가정하십시오. 이 경우에 대한 호출 obj["a"]
은 첫 번째 일치하는 목록 요소 만 리턴합니다. R의 환경을 사용하여 참조 된 이름 당 하나의 항목 만있는 해시와 유사한 동작을 얻을 수 있습니다 (예x <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
x = list(1, 2, 3, 4)
하면 두 가지 모두 같은 결과를 반환하지 않습니다 :x[1]
, 및x[[1]]
. 첫 번째는 목록을 반환하고 두 번째는 숫자 벡터를 반환합니다. 아래로 스크롤하면 Dirk 이이 질문을 올바르게 처리 한 유일한 응답자 인 것 같습니다.