list1
转换为list2
和list2
的最优雅的方式是list1
什么?
list1<- c('a','b','c','d','e','f','g','h','i')
list2<- c('abc','def','ghi')
即:以三个一组的形式接触元素。
感谢:D
list1
转换为list2
和list2
的最优雅的方式是list1
什么?
list1<- c('a','b','c','d','e','f','g','h','i')
list2<- c('abc','def','ghi')
即:以三个一组的形式接触元素。
感谢:D
让list1 <- letters[1:10]
(展示当向量的长度不是 3 的倍数时它是如何工作的)。然后,试试这个:
# method 1 (seems to be the fastest so far,
# my suspicions about loop being slower were wrong)
list2 <- sapply(split(list1, (seq_along(list1)-1) %/% 3), paste, collapse = "")
# alternatively as @flodel mentions
list2 <- tapply(list1, (seq_along(list1)-1) %/% 3, paste, collapse = "")
该tapply
版本的运行时间与sapply+split
(未显示基准测试)相似。
更进一步,在这篇文章中使用@JoshOBrien 的想法
# method 2
pattern <- "(?<=[[:alnum:]]{3})(?=[[:alnum:]])"
strsplit(paste(list1, collapse=""), pattern, perl=TRUE)[[1]]
# [1] "abc" "def" "ghi" "j"
如果您想将最后一部分连接到最后一个(此处为j
to ghi
),那么,请执行以下操作:
pattern <- "(?<=[[:alnum:]]{3})(?=[[:alnum:]]{3})"
strsplit(paste(list1, collapse=""), pattern, perl=TRUE)[[1]]
# [1] "abc" "def" "ghij"
unlist(strsplit(list2, ""), use.names=FALSE)
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
method1
这是method2
和 eddi 的基准测试:
list1 <- sample(letters, 1e5, replace=TRUE)
arun <- function() {
pattern <- "(?<=[[:alnum:]]{3})(?=[[:alnum:]])"
strsplit(paste(list1, collapse=""), pattern, perl=TRUE)[[1]]
}
arun2 <- function() {
unname(sapply(split(list1, (seq_along(list1)-1) %/% 3), paste, collapse = ""))
}
eddi <- function() {
substring(paste(list1, collapse = ""),
seq(1, length(list1), 3),
pmin(seq(3, length(list1)+2, 3), length(list1)))
}
require(microbenchmark)
microbenchmark(t1 <- arun(), t2 <- eddi(), t3 <- arun2(), times=10)
identical(t1, t2) # TRUE
identical(t1, t3) # TRUE
# Unit: milliseconds
# expr min lq median uq max neval
# t1 <- arun() 3352.9867 3400.8627 3512.7037 3585.6499 3635.2182 10
# t2 <- eddi() 3302.0925 3318.4184 3356.2109 3409.9728 3487.7220 10
# t3 <- arun2() 474.9235 494.7407 539.4406 641.2605 907.9072 10
1) Try this:
apply(matrix(list1, 3), 2, paste, collapse = "")
2) and a variant that works even if the length of list1
is not a multiple of 3. Here 3 * ceiling(n/3)
is the length of m
and we subtract n
from that to get the number of positions still to fill:
n <- length(list1)
k <- 3 * ceiling(n / 3) - n
m <- matrix(c(list1, rep("", k)), 3)
apply(m, 2, paste, collapse = "")
3) And here is a different solution which like the second solution here also works if n
is not a multiple of 3:
n <- length(list1)
tapply(list1, c(gl(n, 3, n)), paste, collapse = "")
UPDATE: Added variant that handles length not a multiple of 3 and a different solution as well.
这是另一个版本,它比@Arun 的两种方法都快(与他的方法 1 相比,imo 以牺牲可读性为代价,不幸的是,这比他的方法 2 或这个慢得多)[编辑:经过一些基准测试,这似乎是 Arun 的第一个方法虽然在中小型尺寸上表现不佳,但实际上扩展得更好,在较大尺寸下获胜] [[另一个编辑:格洛腾迪克解决方案是另一个在小尺寸上表现不佳的解决方案,但比 Arun 的第一个解决方案更好方法]]:
substring(paste(list1, collapse = ""),
seq(1, length(list1), 3),
pmin(seq(3, length(list1)+2, 3), length(list1)))
基准
list1 = sample(letters, 10000, replace = T)
microbenchmark(eddi=substring(paste(list1, collapse = ""),seq(1, length(list1), 3),pmin(seq(3, length(list1)+2, 3), length(list1))),
Arun1=sapply(split(list1, (seq_along(list1)-1) %/% 3), paste, collapse = ""),
Arun2=strsplit(paste(list1, collapse=""), pattern, perl=TRUE)[[1]],
Grothendieck=apply(matrix(c(list1, rep("", (3 - length(list1) %% 3) %% 3)), 3), 2, paste, collapse = ""),
times = 100)
#Unit: milliseconds
# expr min lq median uq max neval
# eddi 8.804764 10.17807 11.33133 11.58993 12.69495 100
# Arun1 51.287326 61.74937 65.51151 67.15510 73.98805 100
# Arun2 12.305300 13.52000 14.65123 15.00816 17.20151 100
# Grothendieck 25.043657 29.15488 29.87843 31.02118 45.85889 100
基准测试继续 这有点有趣,在 1e5 时,Arun1 实际上略微超越了其他两个:
list1 = sample(letters, 1e5, replace = T)
microbenchmark(eddi=substring(paste(list1, collapse = ""),seq(1, length(list1), 3),pmin(seq(3, length(list1)+2, 3), length(list1))),
Arun1=sapply(split(list1, (seq_along(list1)-1) %/% 3), paste, collapse = ""),
Arun2=strsplit(paste(list1, collapse=""), pattern, perl=TRUE)[[1]],
Grothendieck=apply(matrix(c(list1, rep("", (3 - length(list1) %% 3) %% 3)), 3), 2, paste, collapse = ""),
times = 30)
#Unit: milliseconds
# expr min lq median uq max neval
# eddi 417.5631 452.6823 480.4397 528.6187 681.0612 30
# Arun1 363.0641 401.6795 420.8844 475.2225 587.3645 30
# Arun2 426.9462 466.5132 506.1106 552.9374 778.7303 30
# Grothendieck 178.2272 206.0161 216.2643 246.3848 280.7988 30
大N长凳
list1 = sample(letters, 1e6, replace = T)
microbenchmark(Arun1=sapply(split(list1, (seq_along(list1)-1) %/% 3), paste, collapse = ""),
+ Grothendieck=apply(matrix(c(list1, rep("", (3 - length(list1) %% 3) %% 3)), 3), 2, paste, collapse = ""), times = 10)
#Unit: seconds
# expr min lq median uq max neval
# Arun1 5.829132 7.654288 8.582664 8.779793 9.168519 10
# Grothendieck 3.196645 3.416421 3.533622 3.725822 3.951419 10