将字符串向量中的元素与定义的元素大小组合在一起,并考虑非事件大小
Combining elements in a string vector with defined element size and accounting for not event sizes
给出的是向量:
vec <- c(LETTERS[1:10])
我希望能够按以下方式组合它:
resA <- c("AB", "CD", "EF", "GH", "IJ")
resB <- c("ABCDEF","GHIJ")
其中向量 vec
的元素根据构成结果向量的新元素的所需大小合并在一起。在 resA
的情况下是 2,在 resB
的情况下是 5。
所需的解决方案特征
- 解决方案应该允许元素大小的灵活性,即我可能想要具有大小为 2 或 20 的元素的向量
- 向量中可能没有足够的元素来匹配所需的块大小,在这种情况下最后一个元素应该相应地缩短(如图所示)
- 这应该没什么区别,但解决方案也应该适用于 words
尝试次数
一开始,我想的是在线上使用一些东西:
c(
paste0(vec[1:2], collapse = ""),
paste0(vec[3:4], collapse = ""),
paste0(vec[5:6], collapse = "")
# ...
)
但这必须进行调整以跳过 vec
的其余 pairs/bigger 组并处理通常较小的最后一组。
vec <- c(LETTERS[1:10])
f1 <- function(x, n){
f <- function(x) paste0(x, collapse = '')
regmatches(f(x), gregexpr(f(rep('.', n)), f(x)))[[1]]
}
f1(vec, 2)
# [1] "AB" "CD" "EF" "GH" "IJ"
或
f2 <- function(x, n)
apply(matrix(x, nrow = n), 2, paste0, collapse = '')
f2(vec, 5)
# [1] "ABCDE" "FGHIJ"
或
f3 <- function(x, n) {
f <- function(x) paste0(x, collapse = '')
strsplit(gsub(sprintf('(%s)', f(rep('.', n))), '\1 ', f(x)), '\s+')[[1]]
}
f3(vec, 4)
# [1] "ABCD" "EFGH" "IJ"
我想说最后一个是最好的,因为 n
对于其他人来说必须是一个因素,否则你会收到警告或回收
编辑 - 更多
f4 <- function(x, n) {
f <- function(x) paste0(x, collapse = '')
Vectorize(substring, USE.NAMES = FALSE)(f(x), which((seq_along(x) %% n) == 1),
which((seq_along(x) %% n) == 0))
}
f4(vec, 2)
# [1] "AB" "CD" "EF" "GH" "IJ"
或
f5 <- function(x, n)
mapply(function(x) paste0(x, collapse = ''),
split(x, c(0, head(cumsum(rep_len(sequence(n), length(x)) %in% n), -1))),
USE.NAMES = FALSE)
f5(vec, 4)
# [1] "ABCD" "EFGH" "IJ"
这是我想出的。使用 Harlan 在 this question 中的想法,您可以将向量拆分为不同数量的块。您还想在这里 lapply()
中使用您的 paste0()
想法。最后,您取消列出一个列表。
unlist(lapply(split(vec, ceiling(seq_along(vec)/2)), function(x){paste0(x, collapse = "")}))
# 1 2 3 4 5
#"AB" "CD" "EF" "GH" "IJ"
unlist(lapply(split(vec, ceiling(seq_along(vec)/5)), function(x){paste0(x, collapse = "")}))
# 1 2
#"ABCDE" "FGHIJ"
unlist(lapply(split(vec, ceiling(seq_along(vec)/3)), function(x){paste0(x, collapse = "")}))
# 1 2 3 4
#"ABC" "DEF" "GHI" "J"
这是另一种方法,使用原始数组。
旁注,使用单词并不简单,因为至少有两种方法可以理解它:您可以单独保留每个单词,或者先折叠它们以获得单独的字符。下一个函数可以处理这两个选项。
vec <- c(LETTERS[1:10])
vec2 <- c("AB","CDE","F","GHIJ")
cuts <- function(x, n, bychar=F) {
if (bychar) x <- unlist(strsplit(paste0(x, collapse=""), ""))
ii <- seq_along(x)
li <- split(ii, ceiling(ii/n))
return(sapply(li, function(y) paste0(x[y], collapse="")))
}
cuts(vec2,2,F)
# 1 2
# "ABCDE" "FGHIJ"
cuts(vec2,2,T)
# 1 2 3 4 5
# "AB" "CD" "EF" "GH" "IJ"
给出的是向量:
vec <- c(LETTERS[1:10])
我希望能够按以下方式组合它:
resA <- c("AB", "CD", "EF", "GH", "IJ")
resB <- c("ABCDEF","GHIJ")
其中向量 vec
的元素根据构成结果向量的新元素的所需大小合并在一起。在 resA
的情况下是 2,在 resB
的情况下是 5。
所需的解决方案特征
- 解决方案应该允许元素大小的灵活性,即我可能想要具有大小为 2 或 20 的元素的向量
- 向量中可能没有足够的元素来匹配所需的块大小,在这种情况下最后一个元素应该相应地缩短(如图所示)
- 这应该没什么区别,但解决方案也应该适用于 words
尝试次数
一开始,我想的是在线上使用一些东西:
c(
paste0(vec[1:2], collapse = ""),
paste0(vec[3:4], collapse = ""),
paste0(vec[5:6], collapse = "")
# ...
)
但这必须进行调整以跳过 vec
的其余 pairs/bigger 组并处理通常较小的最后一组。
vec <- c(LETTERS[1:10])
f1 <- function(x, n){
f <- function(x) paste0(x, collapse = '')
regmatches(f(x), gregexpr(f(rep('.', n)), f(x)))[[1]]
}
f1(vec, 2)
# [1] "AB" "CD" "EF" "GH" "IJ"
或
f2 <- function(x, n)
apply(matrix(x, nrow = n), 2, paste0, collapse = '')
f2(vec, 5)
# [1] "ABCDE" "FGHIJ"
或
f3 <- function(x, n) {
f <- function(x) paste0(x, collapse = '')
strsplit(gsub(sprintf('(%s)', f(rep('.', n))), '\1 ', f(x)), '\s+')[[1]]
}
f3(vec, 4)
# [1] "ABCD" "EFGH" "IJ"
我想说最后一个是最好的,因为 n
对于其他人来说必须是一个因素,否则你会收到警告或回收
编辑 - 更多
f4 <- function(x, n) {
f <- function(x) paste0(x, collapse = '')
Vectorize(substring, USE.NAMES = FALSE)(f(x), which((seq_along(x) %% n) == 1),
which((seq_along(x) %% n) == 0))
}
f4(vec, 2)
# [1] "AB" "CD" "EF" "GH" "IJ"
或
f5 <- function(x, n)
mapply(function(x) paste0(x, collapse = ''),
split(x, c(0, head(cumsum(rep_len(sequence(n), length(x)) %in% n), -1))),
USE.NAMES = FALSE)
f5(vec, 4)
# [1] "ABCD" "EFGH" "IJ"
这是我想出的。使用 Harlan 在 this question 中的想法,您可以将向量拆分为不同数量的块。您还想在这里 lapply()
中使用您的 paste0()
想法。最后,您取消列出一个列表。
unlist(lapply(split(vec, ceiling(seq_along(vec)/2)), function(x){paste0(x, collapse = "")}))
# 1 2 3 4 5
#"AB" "CD" "EF" "GH" "IJ"
unlist(lapply(split(vec, ceiling(seq_along(vec)/5)), function(x){paste0(x, collapse = "")}))
# 1 2
#"ABCDE" "FGHIJ"
unlist(lapply(split(vec, ceiling(seq_along(vec)/3)), function(x){paste0(x, collapse = "")}))
# 1 2 3 4
#"ABC" "DEF" "GHI" "J"
这是另一种方法,使用原始数组。 旁注,使用单词并不简单,因为至少有两种方法可以理解它:您可以单独保留每个单词,或者先折叠它们以获得单独的字符。下一个函数可以处理这两个选项。
vec <- c(LETTERS[1:10])
vec2 <- c("AB","CDE","F","GHIJ")
cuts <- function(x, n, bychar=F) {
if (bychar) x <- unlist(strsplit(paste0(x, collapse=""), ""))
ii <- seq_along(x)
li <- split(ii, ceiling(ii/n))
return(sapply(li, function(y) paste0(x[y], collapse="")))
}
cuts(vec2,2,F)
# 1 2
# "ABCDE" "FGHIJ"
cuts(vec2,2,T)
# 1 2 3 4 5
# "AB" "CD" "EF" "GH" "IJ"