Access lapply index names inside FUN

2019-01-01 03:04发布

Is there a way to get the list index name in my lapply() function?

n = names(mylist)
lapply(mylist, function(list.elem) { cat("What is the name of this list element?\n" })

I asked before if it's possible to preserve the index names in the lapply() returned list, but I still don't know if there is an easy way to fetch each element name inside the custom function. I would like to avoid to call lapply on the names themselves, I'd rather get the name in the function parameters.

10条回答
永恒的永恒
2楼-- · 2019-01-01 03:29

Just write your own custom lapply function

lapply2 <- function(X, FUN){
  if( length(formals(FUN)) == 1 ){
    # No index passed - use normal lapply
    R = lapply(X, FUN)
  }else{
    # Index passed
    R = lapply(seq_along(X), FUN=function(i){
      FUN(X[[i]], i)
    })
  }

  # Set names
  names(R) = names(X)
  return(R)
}

Then use like this:

lapply2(letters, function(x, i) paste(x, i))
查看更多
无色无味的生活
3楼-- · 2019-01-01 03:32

My answer goes in the same direction as Tommy's and caracals, but avoids having to save the list as an additional object.

lapply(seq(3), function(i, y=list(a=14,b=15,c=16)) { paste(names(y)[[i]], y[[i]]) })

Result:

[[1]]
[1] "a 14"

[[2]]
[1] "b 15"

[[3]]
[1] "c 16"

This gives the list as a named argument to FUN (instead to lapply). lapply only has to iterate over the elements of the list (be careful to change this first argument to lapply when changing the length of the list).

Note: Giving the list directly to lapply as an additional argument also works:

lapply(seq(3), function(i, y) { paste(names(y)[[i]], y[[i]]) }, y=list(a=14,b=15,c=16))
查看更多
冷夜・残月
4楼-- · 2019-01-01 03:37

I've had the same problem a lot of times... I've started using another way... Instead of using lapply, I've started using mapply

n = names(mylist)
mapply(function(list.elem, names) { }, list.elem = mylist, names = n)
查看更多
人气声优
5楼-- · 2019-01-01 03:38

Just loop in the names.

sapply(names(mylist), function(n) { 
    doSomething(mylist[[n]])
    cat(n, '\n')
}
查看更多
宁负流年不负卿
6楼-- · 2019-01-01 03:43

You could try using imap() from purrr package.

From the documentation:

imap(x, ...) is short hand for map2(x, names(x), ...) if x has names, or map2(x, seq_along(x), ...) if it does not.

So, you can use it that way :

library(purrr)
myList <- list(a=11,b=12,c=13) 
imap(myList, function(x, y) paste(x, y))

Which will give you the following result:

$a
[1] "11 a"

$b
[1] "12 b"

$c
[1] "13 c"
查看更多
春风洒进眼中
7楼-- · 2019-01-01 03:45

Unfortunately, lapply only gives you the elements of the vector you pass it. The usual work-around is to pass it the names or indices of the vector instead of the vector itself.

But note that you can always pass in extra arguments to the function, so the following works:

x <- list(a=11,b=12,c=13) # Changed to list to address concerns in commments
lapply(seq_along(x), function(y, n, i) { paste(n[[i]], y[[i]]) }, y=x, n=names(x))

Here I use lapply over the indices of x, but also pass in x and the names of x. As you can see, the order of the function arguments can be anything - lapply will pass in the "element" (here the index) to the first argument not specified among the extra ones. In this case, I specify y and n, so there's only i left...

Which produces the following:

[[1]]
[1] "a 11"

[[2]]
[1] "b 12"

[[3]]
[1] "c 13"

UPDATE Simpler example, same result:

lapply(seq_along(x), function(i) paste(names(x)[[i]], x[[i]]))

Here the function uses "global" variable x and extracts the names in each call.

查看更多
登录 后发表回答