Barnaby
Barnaby

Reputation: 1480

Add a series of elements in different locations within a vector

I aim to insert multiple elements to a vector each in different locations. This is the example followed by a number of trials which do not work.

w  <- c( 1,3,2,4,2,3,2,4,5,7,9,3,2,4,2,5,7,4,2 )
u  <- c( 3,7,9,12 )
o  <- c( 10 , 20 , 30 , 40 )

I have tried:

append ( w , o , after = u )  

# which adds the series one time in the first location of after 

fun <- function (x) append ( w , o[[x]] , after = u[[x]] )
lapply ( seq ( length ( u )) , fun )

# which adds one element to the list each time for a new vector producing a  number of vectors 

for (i in length(o)) {
append ( w , o[[i]] , after = u[[i]] )
}
# which basically does nothing

Desired Output

1,3,2,10,4,2,3,2,20,4,5,30,7,9,3,40,2,4,2,5,7,4,2

Is there a way to insert each element one at a time in each specific location? I have seen several questions addressing the append basic for a single element with one location or two elements to be added to the same position however not multiple elements to be added to multiple locations in a vector.

Upvotes: 6

Views: 1905

Answers (4)

Khashaa
Khashaa

Reputation: 7373

x <- numeric(length(w)+length(o))
ind <- u + order(u) #index to insert o vector (which I shamelessly borrowed from Josilber's answer)
x[ind] <- o
x[-ind] <- w
x
# [1]  1  3  2 10  4  2  3  2 20  4  5 30  7  9  3 40  2  4  2  5  7  4  2

Upvotes: 4

Julius Vainora
Julius Vainora

Reputation: 48191

idx <- sort(c(1:length(w), u))
replace(w[idx], c(FALSE, diff(idx) == 0), o)
# [1]  1  3  2 10  4  2  3  2 20  4  5 30  7  9  3 40  2  4  2  5  7  4  2

Upvotes: 1

David Arenburg
David Arenburg

Reputation: 92282

Here's another vectorized way to do this

New <- rep(w, (1:2)[(1:length(w) %in% u) + 1])
New[u + 1:length(u)] <- o
New
# [1]  1  3  2 10  4  2  3  2 20  4  5 30  7  9  3 40  2  4  2  5  7  4  2

This is basically works on subsetting vectors technique, by extracting the values in u twice and the reassigning them with values from o

Upvotes: 4

josliber
josliber

Reputation: 44299

You could do this in a vectorized manner (aka not repeatedly appending) by computing the position of each new element and old element and adding them in one shot:

# Positions of old and new elements
add.pos <- u + order(u)
old.pos <- seq_len(length(w) + length(u))
old.pos <- old.pos[!old.pos %in% add.pos]

# Construct new vector in one shot
new.vec <- rep(NA, length(old.pos))
new.vec[add.pos] <- o
new.vec[old.pos] <- w
new.vec
# [1]  1  3  2 10  4  2  3  2 20  4  5 30  7  9  3 40  2  4  2  5  7  4  2

Since this doesn't involve repeatedly reallocating the space for the vector every time you add an element, it should be faster if you have a large number of elements being added.

Upvotes: 3

Related Questions