89

What are the R equivalents for these Python list comprehensions:

[(i,j) for i,j in zip(index, Values)]
[(i,j) for i,j in enumerate(Values)]
[(i,j) for i,j in enumerate(range(10,20))]   %MWE, indexing or enumerating to 
                                            %keep up with the index, there may 
                                            %be some parameter to look this up

Example with Output

>>> [(i,j) for i,j in enumerate(range(10,20))]
[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]

I have solved this problem earlier with some trick in R but cannot remember anymore, the first idea was itertools -pkg but I am hoping to find a more idiomatic way of doing things.

4

9 回答 9

55

蟒蛇的答案enumerate

在 R 中,列表是有序的(请参阅此答案)。因此,您所需要的只是索引键(使用names()[i])或值(使用[[i]])。

使用seq_along(或者可以做for(i in 1:length(mylist)){...}):

> mylist <- list('a'=10,'b'=20,'c'=30)
> for (i in seq_along(mylist)){
+   print(paste(i,names(mylist)[i],mylist[[i]]))
+ }
[1] "1 a 10"
[1] "2 b 20"
[1] "3 c 30"

蟒蛇的答案zip

请参阅上述答案之一以模仿元组列表。我的偏好是数据框,如 BondedDust 的回答所示:

> x <- 1:3
> y <- 4:6
> data.frame(x=x, y=y)
  x y
1 1 4
2 2 5
3 3 6
于 2014-06-24T13:09:20.480 回答
43

围绕 R 的列表理解进行了一些讨论,例如heretherehash包甚至提供了类似字典的结构。然而,正如其他人所说,如果没有清楚地了解应该使用什么,就很难尝试将一种语言设施映射到另一种语言设施(即使这是编程语言比较实际提供的)。例如,我可以zip()在 R 中模仿 Python,如下所示:

Python

In [1]: x = [1,2,3]
In [2]: y = [4,5,6]
In [3]: zip(x, y)
Out[3]: [(1, 4), (2, 5), (3, 6)]

R

> x <- 1:3
> y <- 4:6
> list(x, y)                     # gives a simple list
> as.list(paste(x, y))           # three tuples, as a list of characters
> mapply(list, x, y, SIMPLIFY=F) # gives a list of 3 tuples
> rbind(x, y)                    # gives a 2x3 matrix 

可以看出,这实际上取决于您之后想要对结果做什么。

于 2012-02-14T20:51:44.477 回答
10

zip并且enumerate在 R 中实现起来并不特别困难:

#' zip(1:5,1:10)
zip <- function(...) {
  mapply(list, ..., SIMPLIFY = FALSE)
}

枚举很容易定义为zip

#' enumerate(l=LETTERS)
enumerate <- function(...) {
  zip(ix=seq_along(..1), ...)
}

由于这些是适当的函数,我们可以使用...它们使它们相当灵活和简洁,并利用 mapply 的行为,例如回收输入和正确命名输出。

于 2019-08-19T23:05:20.743 回答
9

另一个创建向量列表的选项是使用 @peterhurford 在这里看到的 Map 函数:https ://rdrr.io/github/peterhurford/funtools/src/R/zippers.R

> x <- 1:3
> y <- 4:6
> z <- 7:9
> Map(c, x, y, z)
[[1]]
[1] 1 4 7

[[2]]
[1] 2 5 8

[[3]]
[1] 3 6 9
于 2019-01-25T14:32:55.047 回答
6

如果那是矩阵的 Python 打印表示,则此代码:

j <- 10:20
matrix(c(seq_along(j), j), ncol=2)
#------------
      [,1] [,2]
 [1,]    1   10
 [2,]    2   11
 [3,]    3   12
 [4,]    4   13
 [5,]    5   14
 [6,]    6   15
 [7,]    7   16
 [8,]    8   17
 [9,]    9   18
[10,]   10   19
[11,]   11   20

你仍然让我们这些不是 Python 用户的人对你想要的输出结构一无所知。您使用术语“列表”,但输出建议一组有序的元组。

鉴于@chi 的指导,我们可能还建议使用非常以 R 为中心的“数据框”结构

x <- 1:3
y <- 4:6
dfrm <- data.frame(x=x, y=y)

...它在列类型方面具有列表的灵活性,在行和列索引方面具有矩阵的访问特性。或者可以使用 hhh 的请求并创建 j 向量的隐式索引值10:20,使用rownames默认从“1”开始的向量,但可以将其更改为从“0”开始的字符向量

dfrm <- data.frame(j=10:20)
dfrm[3, ]
#[1] 12

 rownames(dfrm) <- 0:10
 dfrm["0",]
# [1] 10

不幸的是,粗心的人会发现 dfrm[0, ] 不是一个愉快的调用,它返回长度为 0 的向量。

于 2012-02-14T18:12:55.057 回答
4

为了使用带有枚举的 Python 样式列表推导,例如枚举列表,一种方法是安装 List-comprehension 包LC(2018 年开发)和 itertools 包(2015 年开发)。

R中的列表推导

你可以在这里LC找到包。

install.packages("devtools")
devtools::install_github("mailund/lc")

例子

> library(itertools); library(lc)
> lc(paste(x$index, x$value), x=as.list(enumerate(rnorm(5))), )
[[1]]
[1] "1 -0.715651978438808"

[[2]]
[1] "2 -1.35430822605807"

[[3]]
[1] "3 -0.162872340884235"

[[4]]
[1] "4 1.42909760816254"

[[5]]
[1] "5 -0.880755983937781"

编程语法还不像 Python 那样干净和优美,但在功能上可以正常工作,并且它的帮助概述:

“语法如下: lc(expr, lists, predicates) 其中 expr 是要为列表中的所有元素计算的某个表达式,其中列表是一个或多个命名列表,其中这些列表由名称和表达式名称指定= list_expr,其中谓词是应该计算为布尔值的表达式。例如,要从列表 x 中获取所有偶数平方的列表,我们可以写成 lc(x ** 2, x = x, x % % 2 == 0)。调用 lc 的结果是一个由 expr 中的表达式构造的列表,用于输入列表中谓词评估为真的所有元素。

请注意,您可以将谓词留空,例如在上面的示例中。

Python 风格的迭代工具和枚举

您可以使用与 Python 的 itertools 非常相似的 R 的 itertools,进一步在 Cran

library(itertools)

在哪里描述

“用于创建迭代器的各种工具,许多模仿 Python itertools 模块中的函数,还有一些模仿 'snow' 包中的函数。”

例子。枚举

> for (a in as.list(enumerate(rnorm(5)))) { print(paste(a$index, "index:", a$value))}
[1] "1 index: 1.63314811372568"
[1] "2 index: -0.983865948988314"
[1] "3 index: -1.27096072277818"
[1] "4 index: 0.313193212706331"
[1] "5 index: 1.25226639725357"

例子。使用 ZIP 枚举

> for (h in as.list(izip(a=1:5, b=letters[1:5]))) { print(paste(h$a, "index:", h$b))}
[1] "1 index: a"
[1] "2 index: b"
[1] "3 index: c"
[1] "4 index: d"
[1] "5 index: e"
于 2018-08-31T17:58:38.837 回答
1

对于python,R中的“枚举”等效项。将向量存储在列表中并使用索引对其进行迭代应该可以正常工作。

vect1 <- c('A', 'B', 'C')
vect2 <- c('a', 'b', 'c')

# eqiv to zip values:
idx_list <- list(vect1, vect2)
idx_vect <- c(1:length(idx_list[[1]]))

for(i in idx_vect){
    x <- idx_list[[1]][i]
    j <- idx_list[[2]][i]
    print(c(i, x, j))
}

输出:

[1] "1" "A" "a"
[1] "2" "B" "b"
[1] "3" "C" "c"

R 'list' 是一个很好的存储向量和保留索引的银行。

于 2020-12-11T17:52:20.787 回答
0

这可以使用两个粘贴语句来实现:

str1 <- paste(1:11, 10:20, sep=",", collapse='), (')
paste("(", str1, ")", sep = "")

输出将如下所示:

'(1,10), (2,11), (3,12), (4,13), (5,14), (6,15), (7,16), (8,17), (9,18), (10,19), (11,20)'
于 2020-04-30T10:03:18.653 回答
0
# similar to python. return a list of list. Short sequences get recycled.
zip <- function(...){ 
    all.list <- list(...)
    ele.names <- names(all.list)
    max.length <- max(sapply(all.list, length))
    lapply(0:(max.length - 1), function(i) {
        res <- lapply(all.list, function(l) l[i %% length(l) + 1]) 
        names(res) <- ele.names
        res
    })
}
于 2018-03-16T08:46:22.450 回答