목록 요소가 있는지 테스트하는 방법은 무엇입니까?
문제
목록의 요소가 존재하는지 테스트하려고 합니다. 여기 예제가 있습니다.
foo <- list(a=1)
exists('foo')
TRUE #foo does exist
exists('foo$a')
FALSE #suggests that foo$a does not exist
foo$a
[1] 1 #but it does exist
이 예에서, 나는 알고 있습니다.foo$a
존재하지만 테스트가 반환됩니다.FALSE
.
찾아봤습니다?exists
그리고 그것을 발견했습니다.with(foo, exists('a')
돌아온다TRUE
하지만 그 이유를 이해하지 못합니다.exists('foo$a')
돌아온다FALSE
.
문의사항
- 왜 그럴까요?
exists('foo$a')
돌아가다FALSE
? - 의 사용 여부
with(...)
선호하는 접근법?
이것은 사실 여러분이 생각하는 것보다 조금 더 까다롭습니다.목록에 실제로 NULL 요소가 포함될 수 있으므로 확인하기에 충분하지 않을 수 있습니다.is.null(foo$a)
더 엄격한 테스트는 이름이 목록에 실제로 정의되어 있는지 확인하는 것입니다.
foo <- list(a=42, b=NULL)
foo
is.null(foo[["a"]]) # FALSE
is.null(foo[["b"]]) # TRUE, but the element "exists"...
is.null(foo[["c"]]) # TRUE
"a" %in% names(foo) # TRUE
"b" %in% names(foo) # TRUE
"c" %in% names(foo) # FALSE
...그리고.foo[["a"]]
보다 안전합니다.foo$a
후자는 부분 일치를 사용하므로 더 긴 이름과도 일치할 수 있습니다.
x <- list(abc=4)
x$a # 4, since it partially matches abc
x[["a"]] # NULL, no match
[UPDATE] 다음 질문으로 돌아갑니다. 이유는 무엇입니까?exists('foo$a')
작동하지 않습니다.그exists
함수는 변수가 환경에 있는지 여부만 확인하고 개체의 일부가 있는지 여부는 확인하지 않습니다.현"foo$a"
문학적으로 해석됩니다."foo$a"라는 변수가 있나요? ...그리고 그 대답은FALSE
...
foo <- list(a=42, b=NULL) # variable "foo" with element "a"
"bar$a" <- 42 # A variable actually called "bar$a"...
ls() # will include "foo" and "bar$a"
exists("foo$a") # FALSE
exists("bar$a") # TRUE
명명된 요소를 확인하는 가장 좋은 방법은 다음을 사용하는 것입니다.exist()
그러나 위의 답변은 이 기능을 제대로 사용하지 않습니다.다음을 사용해야 합니다.where
목록 내 변수를 확인하는 인수입니다.
foo <- list(a=42, b=NULL)
exists('a', where=foo) #TRUE
exists('b', where=foo) #TRUE
exists('c', where=foo) #FALSE
아직 나오지 않은 한 가지 해결책은 길이를 사용하는 것인데, 이는 NULL을 성공적으로 처리합니다.제가 알기로는 NULL을 제외한 모든 값의 길이가 0보다 큽니다.
x <- list(4, -1, NULL, NA, Inf, -Inf, NaN, T, x = 0, y = "", z = c(1,2,3))
lapply(x, function(el) print(length(el)))
[1] 1
[1] 1
[1] 0
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 3
따라서 명명된 인덱스와 번호가 지정된 인덱스 모두에서 작동하는 간단한 함수를 만들 수 있습니다.
element.exists <- function(var, element)
{
tryCatch({
if(length(var[[element]]) > -1)
return(T)
}, error = function(e) {
return(F)
})
}
요소가 존재하지 않으면 tryCatch 블록에 의해 탐지된 범위 외 상태가 발생합니다.
다음은 다른 답변에서 제안된 방법의 성능 비교입니다.
> foo <- sapply(letters, function(x){runif(5)}, simplify = FALSE)
> microbenchmark::microbenchmark('k' %in% names(foo),
is.null(foo[['k']]),
exists('k', where = foo))
Unit: nanoseconds
expr min lq mean median uq max neval cld
"k" %in% names(foo) 467 933 1064.31 934 934 10730 100 a
is.null(foo[["k"]]) 0 0 168.50 1 467 3266 100 a
exists("k", where = foo) 6532 6998 7940.78 7232 7465 56917 100 b
목록을 여러 번 액세스하는 빠른 사전으로 사용할 계획이라면,is.null
접근이 유일한 실행 가능한 선택일 수 있습니다.저는 O(1)라고 가정하지만, 반면에.%in%
접근법이 O(n)입니까?
약간 수정된 버전인 of @salient.sa lamander는 전체 경로를 확인하고 싶다면 이것을 사용할 수 있습니다.
Element_Exists_Check = function( full_index_path ){
tryCatch({
len_element = length(full_index_path)
exists_indicator = ifelse(len_element > 0, T, F)
return(exists_indicator)
}, error = function(e) {
return(F)
})
}
rlang::has_name()
이것도 가능합니다.
foo = list(a = 1, bb = NULL)
rlang::has_name(foo, "a") # TRUE
rlang::has_name(foo, "b") # FALSE. No partial matching
rlang::has_name(foo, "bb") # TRUE. Handles NULL correctly
rlang::has_name(foo, "c") # FALSE
보시다시피, @Tommy가 기본 R을 사용하여 처리하는 방법을 보여준 모든 사례를 본질적으로 처리하고 이름 없는 항목이 있는 목록에 대해 작동합니다.그래도 추천합니다.exists("bb", where = foo)
가독성에 대한 다른 답변에서 제안한 바와 같이, 그러나has_name
이름이 지정되지 않은 항목이 있는 경우 대신 사용할 수 있습니다.
사용하다purrr::has_element
목록 요소의 값을 확인합니다.
> x <- list(c(1, 2), c(3, 4))
> purrr::has_element(x, c(3, 4))
[1] TRUE
> purrr::has_element(x, c(3, 5))
[1] FALSE
언급URL : https://stackoverflow.com/questions/7719741/how-to-test-if-list-element-exists
'programing' 카테고리의 다른 글
Git 태그는 현재 분기에만 적용됩니까? (0) | 2023.07.12 |
---|---|
도커별 워드프레스 프로젝트에서 컨테이너 디렉토리 /var/www/html을 다른 경로로 변경하는 방법은 무엇입니까? (0) | 2023.07.12 |
동면.최대 절전 모드 버전을 4.2.0으로 업그레이드하면 INTEGER를 사용할 수 없습니다.CR1 (0) | 2023.07.12 |
집계 addToSet 결과 정렬 중 (0) | 2023.07.12 |
Contains()를 사용할 때 2100 매개 변수 제한(SQL Server)을 초과하는 경우 (0) | 2023.07.12 |