質問

In R, I have a list that contains both named elements and unnamed elements. I want to iterate over the whole list and apply a function that only takes the element for unnamed elements and apply a different function to both the name and the attached elements for named elements.

In pseudo code, the function would look something like if(named) f(name, list[[name]]) else g(element), where list[[name]] is the element stored with that name.

For example, if the list element is unnamed then the element is returned. If the list element is named, then I want to return the name repeated a number of times equal to the element (assume that the element is an integer).

If I had ll = list(a = 5, b = 3, 9, 18) then the function should return a a list with elements

[[1]]
[1] "aaaaa"

[[2]]
[1] "bbb"

[[3]]
[1] 9

[[4]]
[1] 18

I thought about iterating over names(ll) but this cannot access the unnamed elements. Both names[[3]] and names[[4]] are equal to "" and ll[[""]] = NULL.

The process doesn't need to be very efficient so I could use

for(i in 1:length(names(ll)))
  if(names(ll)[[i]] == "")
    g(ll[[i]])
  else
    f(names(ll)[[i]], ll[[names(ll)[[i]])

but I was looking for a neater solution.

役に立ちましたか?

解決

ll = list(a = 5, b = 3, 9, 18)

lapply(seq_along(ll), function(x){
         if(names(ll[x]) == ""){
            ll[[x]]
         }else{
            paste0(rep(names(ll[x]), times =ll[[x]]), collapse = '')
         }
            }
      )

[[1]]
[1] "aaaaa"

[[2]]
[1] "bbb"

[[3]]
[1] 9

[[4]]
[1] 18

他のヒント

You could make a little named function

named<-function(x) names(x)!=''

and then use it on your list:

ll <- list(a = 5, b = 3, 9, 18)
ll[named(ll)]
# $a
# [1] 5
# 
# $b
# [1] 3

Or the other way:

ll[!named(ll)]
# [[1]]
# [1] 9
# 
# [[2]]
# [1] 18 

But this will fail if you have no names on the list at all, so you could modify named to handle that case:

named<-function(x) if (is.null(names(x))) rep(FALSE,length(x)) else names(x)!=''
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top