Reputation: 98
I have to modify %in%
operator which will find an objects in a list.
I have a list:
list1 <- list(c(5,6), 6, list(2, c(5, 6)), "string")
Non-modified %in%
operator after testing these values:
c(5,6) %in% list1
6 %in% list1
2 %in% list1
list(2, c(5,6)) %in% list1
will return:
TRUE
TRUE
FALSE
FALSE
but for list(2, c(5,6)) %in% list1
I need it to return TRUE
as it is an element of this list.
I have to implement it without using loops and I got stuck.
Upvotes: 4
Views: 112
Reputation: 48221
In case all you want is to detect this element in the list rather than necessarily defining an operator, there is no need for anything fancy; we can simply add another list
as to make it clear that it's a single element that we are interested in:
list(list(2, c(5,6))) %in% list1
# [1] TRUE
Update: while this may be intuitive, what exactly is happening isn't so clear. As @BenBolker observed, %in%
is based on match
, whose description says
Factors, raw vectors and lists are converted to character vectors, and then x and table are coerced to a common type (the later of the two types in R's ordering, logical < integer < numeric < complex < character) before matching.
So, it would seem that list(list(2, c(5,6)))
and list1
first get (somehow) converted to character vectors. As we need to maintain the structure and ordering one sensible guess that it directly means
as.character(list(list(2, c(5,6)))) %in% as.character(list1)
where
as.character(list(list(2, c(5,6))))
# [1] "list(2, c(5, 6))"
as.character(list1)
# [1] "c(5, 6)" "6" "list(2, c(5, 6))" "string"
Upvotes: 2
Reputation: 3736
purrr::has_element
should give you what you want:
purrr::has_element(list1, c(5,6))
#[1] TRUE
purrr::has_element(list1, 6)
#[1] TRUE
purrr::has_element(list1, 2)
#[1] FALSE
purrr::has_element(list1, list(2, c(5,6)))
#[1] TRUE
You could also write your own infix function that wraps around this function and works like %in%
:
`%in2%` <- function(lhs, rhs) purrr::has_element(rhs, lhs)
c(5,6) %in2% list1
#[1] TRUE
6 %in2% list1
#[1] TRUE
2 %in2% list1
#[1] FALSE
list(2, c(5,6)) %in2% list1
#[1] TRUE
Upvotes: 4