user3385769
user3385769

Reputation: 161

Obtain "key" from "value" in R

I have created a list which itself consists of several lists. I am trying to determine an efficient way to get the "key" from the "value". I.e. if I specify ("cat" or "dog"), ("fish" or "chicken"), ("horse" or "donkey") how can I return "pet", "food", and "work" respectively. I have tried to create a method with a for loop since I am not sure how else to approach with indexing by name.

pet <- c("cat", "dog")
food <- c("fish", "chicken")
work <- c("horse", "donkey")

types <- c("pet", "food", "work")

animal.list <- vector(mode = "list", length = length(types))
names(animal.list) <- types

for (i in types)
{
  animal.list[[i]] <-  vector(mode = "list", length = length(c("a", "b")))
  names(animal.list[[i]]) <- c("a", "b")
  animal.list[[i]][["a"]] <- eval(parse(text = i))[[1]]
  animal.list[[i]][["b"]] <- eval(parse(text = i))[[2]]

}

My attempt would look something like this, but hopefully I could use some kind of which( %in%) statement to do it more efficiently/compactly.

f <- function(x)
{
    ret <- NULL
    for (i in animals)
    {

         if(x == animal.list[[i]][["a"]] | x == animal.list[[i]][["b"]])
         {
             ret <- i
         }
     }

}

Upvotes: 4

Views: 2932

Answers (2)

BrodieG
BrodieG

Reputation: 52687

You can create a lookup table with stack, and then use match to find the values:

animals <- stack(list(pet=pet, food=food, work=work))
f <- function(x) as.character(animals[match(x, animals[[1]]), 2])

Then:

f("cat")
# [1] "pet"
f("horse")
# [1] "work"

Note %in% is just a variation on match.

You can also use R's built in character lookup:

animal.vec <- as.character(animals[[2]])
names(animal.vec) <- animals[[1]]
animal.vec[c("cat", "horse")]
#   cat  horse 
# "pet" "work

Upvotes: 7

Ari B. Friedman
Ari B. Friedman

Reputation: 72769

You can select multiple elements of a list with a single bracket rather than a double. Combining that with any and %in%:

#  ("cat" or "dog")
idx <- sapply( animal.list, function(x) any( x %in% c("cat", "dog")) )
names( animal.list )[ idx ]

Upvotes: 1

Related Questions