Home > front end >  concise way to get names of list elements
concise way to get names of list elements

Time:12-12

I have a list, called breakdown, that partitions elements of a vector called theNames. I want another vector, with the same length as theNames, where each element of the new vector corresponds to a name of the list. In other words, if I have

breakdown <- list(first = c('a','b'), second = c('c','d'))
theNames <- c('a','b','c','d')

then what I want is c('first','first','second','second').

The following works, but is not very concise. Is there a simpler way?

tmp <- sapply(theNames, function(name){ rapply(breakdown, function(elem) { name %in% elem })})
apply(tmp, 2, function(col) rownames(tmp)[col]) 

Edit: I forgot to mention this: the order of the result should correspond with the order of theNames.

CodePudding user response:

Here is an approach that doesn't assume that theNames is the same as unlist(breakdown).

map <- setNames(rep(names(breakdown), lengths(breakdown)), unlist(breakdown))
map[theNames]
       a        b        c        d 
 "first"  "first" "second" "second" 
map[rev(theNames)]
       d        c        b        a 
"second" "second"  "first"  "first" 
map[rep(theNames, 2L)]
       a        b        c        d        a        b        c        d 
 "first"  "first" "second" "second"  "first"  "first" "second" "second" 

You can pass the result to unname if you don't want it to have names.

CodePudding user response:

Assuming we have a named list of vectors, repeat each name the number of times given by lengths.

rep(names(breakdown), lengths(breakdown))
## [1] "first"  "first"  "second" "second"

Added

An additional condition was added later that theNames may not be in the same order as breakdown. Using b to stand for breakdown we have the following. In this case it gives the same answer as above.

rep(names(b), lengths(b))[match(theNames, unlist(b))]

CodePudding user response:

Maybe you can try stack

> with(
    stack(breakdown),
    setNames(ind, values)
  )
     a      b      c      d
 first  first second second
Levels: first second

CodePudding user response:

library(tidyverse)

breakdown <- list(first = c('a','b'), second = c('c','d'))
theNames <- c('a','b','c','d')

theNames %>% 
  map(function(nms)
    map(breakdown, ~any( nms == .)) %>%
      keep(~.)) %>%
  map(~names(.)) %>% 
  unlist
#> [1] "first"  "first"  "second" "second"

Created on 2021-12-11 by the reprex package (v2.0.1)

  •  Tags:  
  • r
  • Related