1

There's a workaround to allow access the index inside a s/lapply

e.g.

x <- list(a=11,b=12,c=13) 
lapply(seq_along(x), function(y, n, i) { paste(n[[i]], y[[i]]) }, y=x, n=names(x))

Is there any function like s/lapply (or like purrr::map()) which allows access to the index in the simplest way possible, which I guess would be to simply supply its desired name to the initial function call and nothing more;

map_with_index <- function(.x, .f, index) {
  # Same as purrr::map()
  # ..but whatever string is provided to 'index' parameter becomes the index
  # and is accessible inside the function
  }

Does something already exist, or is it possible to define a custom function that does this?

Note: One could argue that the s/lapply technique above achieves what's required. But the counter argument is that it adds unwanted complexity even in its MRE, let alone in complicated real life settings, hence, a simplification would be valuable.

stevec
  • 41,291
  • 27
  • 223
  • 311
  • Do you need `Map(paste, names(x), x)` ? Or in your case perhaps `as.list(paste(names(x), x))` – markus Jul 08 '20 at 13:19
  • @markus my first time seeing `Map` and I don't think it solves. Basically suppose I have a loop and wish to convert the process to a function so it can be used with lapply/map, but suppose there's some reason to need to know what iteration the loop is up to. Easy in a loop, but a little complicated using *apply/map. – stevec Jul 08 '20 at 13:25

1 Answers1

2

You need to look at the purrr::imap family of functions. Here is a simple example:

set.seed(123)
s <- sample(10)
purrr::imap_chr(s, ~ paste0(.y, ": ", .x))

Output

[1] "1: 3"  "2: 10" "3: 2"  "4: 8"  "5: 6"  "6: 9"  "7: 1"  "8: 7"  "9: 5"  "10:4"
slava-kohut
  • 4,203
  • 1
  • 7
  • 24
  • Wow. that is elegant. Is `.y` always the index and `.x` always the value? – stevec Jul 08 '20 at 13:30
  • 2
    Here I am using a formula shortcut. The first argument is always the value, the second argument is always the position/name. Think about `purrr::imap` as `purr::map2(x, seq_along(x), ...)` or `purr::map2(x, names(x), ...)`. – slava-kohut Jul 08 '20 at 13:35
  • @slava-kohut good notice; never thought of passing index as a separate argument, manually – ivan866 May 23 '22 at 17:43
  • Worth noting that imap does not allow you to control whether the second argument is the position or name for a named vector; it always uses names when available. – Brandon Aug 20 '23 at 15:28