2

I have two lists x and y, and a vector of indices where.

x <- list(a = 1:4, b = letters[1:6])
y <- list(a = c(20, 50), b = c("abc", "xyz"))
where <- c(2, 4)

I want to insert y into x at the indices in where, so that the result is

list(a = c(1,20,2,50,3,4), b = c("a", "abc", "b", "xyz", "c", "d", "e", "f"))
#$a
#[1]  1 20  2 50  3  4
#
#$b
#[1] "a"   "abc" "b"   "xyz" "c"   "d"   "e"   "f"  

I've been trying it with append, but it's not working.

lapply(seq(x), function(i) append(x[[i]], y[[i]], after = where[i]))
#[[1]]
#[1]  1  2 20 50  3  4
#
#[[2]]
#[1] "a"   "b"   "c"   "d"   "abc" "xyz" "e"   "f"  

This is appending at the wrong index. Plus, I want to retain the list names in the process. I also don't know if append is the right function for this, since I've literally never seen it used anywhere.

What's the best way to insert values from one list into another list using an index vector?

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • I don't understand your output. Should the data from 'y' replace data from 'x' or be inserted at those indeces but keep all of 'x'? In your given output, in `$b` the letter `b` was replaced but the letter `d` was not, and you had a similar thing in `$a`. Can you clarify? – John Paul Sep 06 '14 at 02:09
  • Inserted. It says that in the question. :) – Rich Scriven Sep 06 '14 at 02:16
  • i reckon this [might help](http://stackoverflow.com/q/16443260/471093) – baptiste Sep 06 '14 at 02:31

2 Answers2

1

Here I created a APPEND function that is an iterative (via Reduce) version of append:

APPEND <- function(x, where, y)
   Reduce(function(z, args)do.call(append, c(list(z), args)),
          Map(list, y, where - 1), init = x)

Then you just need to call that function via Map:

Map(APPEND, x, list(where), y)
flodel
  • 87,577
  • 21
  • 185
  • 223
  • `do.call` interests me, but I don't quite understand what's happening. In `Reduce`, what is `z`? – Rich Scriven Sep 06 '14 at 03:18
  • Granted, it is not straight forward but play a bit with `Reduce` and you will probably get it. `Reduce(f, y, x)` starts from `x` and replaces it iteratively like this: `x <- f(x, y[1]); x <- f(x, y[2]); x <- f(x, y[3]);` etc. For `f` I could not use `append` directly because it uses three arguments, so I had to rely on `do.call` to create a function that only takes two arguments: `function(z, args)`. – flodel Sep 06 '14 at 14:58
1

How about an mapply solution

x <- list(a = 1:4, b = letters[1:6])
y <- list(a = c(20, 50), b = c("abc", "xyz"))
where <- c(2, 4)

mapply(function(x,y,w) {
    r <- vector(class(x), length(x)+length(y))
    r[-w] <- x
    r[w] <- y
    r
}, x, y, MoreArgs=list(where), SIMPLIFY=FALSE)

which returns

$a
[1]  1 20  2 50  3  4

$b
[1] "a"   "abc" "b"   "xyz" "c"   "d"   "e"   "f"  

which seems to be the results you desire.

MrFlick
  • 195,160
  • 17
  • 277
  • 295