在R中交错列表

36

假设我在R语言中有两个列表,长度不一定相等,例如:

 a <- list('a.1','a.2', 'a.3')
 b <- list('b.1','b.2', 'b.3', 'b.4')

如何构建一个交错元素列表的最佳方式,其中一旦添加了较短列表的元素,剩余的长列表元素将附加在末尾?例如:

interleaved <- list('a.1','b.1','a.2', 'b.2', 'a.3', 'b.3','b.4')

不使用循环。我知道mapply适用于两个列表长度相等的情况。

5个回答

43

这里有一种方法:

idx <- order(c(seq_along(a), seq_along(b)))
unlist(c(a,b))[idx]

# [1] "a.1" "b.1" "a.2" "b.2" "a.3" "b.3" "b.4"

正如@James所指出的那样,由于你需要返回一个列表,你应该这样做:

(c(a,b))[idx]

我认为在编辑后,现在唯一的要求是较短的列表必须是a,较长的列表必须是b,但这很容易检查。 - joran
我认为我只是对 OP 的陈述进行了更严格的解释。如果你从较短列表的第一个元素开始交错,然后以此类推,“较长列表的剩余元素附加在末尾”才真正有意义。 - joran
输出难道不应该是一个列表吗? - James
3
不使用unlist,而是只使用c(a,b)[idx]可能更好,因为通常情况下,使用unlist会破坏复杂对象的数据结构。 - James

33

在调查一个类似问题时,我发现这个由Gabor Grothendieck(即@GGrothendieck?)提出的解决方案非常优美,适用于某些情况:

c(rbind(a,b))

ab都是列表,或者都是向量时,这个方法同样适用。它不能精确解决OP的问题,因为当ab的长度不同时,它会重复使用较短序列的元素并打印警告。然而,由于这个方法简单而优雅,并且提供了一个答案给一个非常相似的问题--一些人(比如我)在查找这个页面时得到的答案--所以值得将其作为一个答案添加进来。


我正在研究如何将data.frame转换为XML格式的纯字符串,而不需要太多依赖。这是处理行时打开/关闭标签最简洁的方法(使用apply)!我将rbind(不使用c)包装在paste和collapse = ""中。 - mlt
这似乎不能处理日期,原因不明。它被转换成了整数列表。 - wpkzz

5

这里有一个使用 ggplot2 中的 interleave 函数的选项。我相信这可以得到改进,但这是一个开始:

require(ggplot2)
Interleave <- function(x,y){
    v <- list(x,y)
    lengths <- sapply(v,length)
    mn <- min(lengths)
    v <- v[order(lengths)]
    c(ggplot2:::interleave(v[[1]],v[[2]][seq_len(mn)]),v[[2]][(mn+1):length(v[[2]])])
}

Interleave(a,b)
Interleave(b,a)

特别是,如果这些列表的长度实际上相同,那么这将会产生奇怪的结果。也许有人会提出一种更好的方法来处理最后一行中v[[2]]的索引,从而避免出现这种退化情况。

5
interleave(a, b)

# unlist(interleave(a, b))
# [1] "a.1" "b.1" "a.2" "b.2" "a.3" "b.3" "b.4"


interleave <- function(a, b) { 

  shorter <- if (length(a) < length(b)) a else b
  longer  <- if (length(a) >= length(b)) a else b

  slen <- length(shorter)
  llen <- length(longer)


  index.short <- (1:slen) + llen
  names(index.short) <- (1:slen)

  lindex <- (1:llen) + slen
  names(lindex) <- 1:llen


  sindex <- 1:slen
  names(sindex) <- 1:slen

  index <- c(sindex, lindex)
  index <- index[order(names(index))]

  return(c(a, b)[index])

}

2

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