purrr的map*函数族中的计数器

8

在对向量/列表应用循环函数时,我经常需要某种计数器/索引值。使用基本的循环函数时,可以通过将1逐步添加到某个初始值来创建此索引。考虑以下示例:

lets <- letters[1:5]

n = 0
for (le in lets){
  n = n+1
  print(paste(le,"has index",n))
}
#> [1] "a has index 1"
#> [1] "b has index 2"
#> [1] "c has index 3"
#> [1] "d has index 4"
#> [1] "e has index 5"

我使用purrr包中的循环函数通过map2才能访问此类索引值。是否有更优雅的方法只使用purrr::map()实现此功能?

library(purrr)


map2(lets,1:length(lets),~paste(.x,"has index",.y))

#> [[1]]
#> [1] "a has index 1"
#> 
#> [[2]]
#> [1] "b has index 2"
#> 
#> [[3]]
#> [1] "c has index 3"
#> 
#> [[4]]
#> [1] "d has index 4"
#> 
#> [[5]]
#> [1] "e has index 5"
2个回答

6
你要寻找的最接近的解决方案是purrr::imap,文档中描述它为:

如果x有名称,则是map2(x,names(x),...)的简写形式,否则是map2(x, seq_along(x), ...)的简写形式。

下面的代码可行:
lets <- letters[1:5]

purrr::imap(lets, ~print(paste(.x, "has index", .y)))

我猜你是想创建一个新对象并将其存储在一个新变量中。如果你想显示输出(就像在这个例子中,结果是一个print到控制台),你应该使用等效的函数iwalk,它会隐式地返回其输出。


4
尝试使用imap
lets <- letters[1:5]
purrr::imap(lets, ~paste(.x,"has index",.y))
#[[1]]
#[1] "a has index 1"

#[[2]]
#[1] "b has index 2"

#[[3]]
#[1] "c has index 3"

#[[4]]
#[1] "d has index 4"

#[[5]]
#[1] "e has index 5"

请注意,如果元素被命名,imap将使用.x的元素名称作为.y参数。如果您不想这样做,请使用imap(unname(...), ...) - 感谢@Moody_Mudskipper。
一个base R的方法可能是:
sprintf("%s has index %d", lets, seq_along(lets))
# [1] "a has index 1" "b has index 2" "c has index 3" "d has index 4" "e has index 5"

1
请注意,如果元素被命名,则imap将使用元素的名称作为.y。在这种情况下,请先使用unname函数取消元素的命名! - moodymudskipper
2
谢谢你的回答!@A. Stam同时发布了相同的答案。我接受了他的答案,因为它包括了文档中的一个揭示性摘录(而且他的声望较低)。 - Ratnanil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接