remove vector-elements from vector

Viewed 615

This looks easy enough, but I keep bumping my head.

I have the numeric vector v1

v1 <- c(1,1,3,5,7,7)

And I have a numeric vector v2. v2 is always a subset of v1.
I want to remove the all elements from v2 from v1, but only one (and exaclty one) v1 element per v2 element.

desired output

if v2 <- c(3,5) I want to keep c(1,1,7,7) from v1. This one is easy using v1[-match(v2, v1)].
if v2 <- c(1,7) I want to keep c(1,3,5,7) from v1. also, v1[-match(v2, v1)] does the trick.
if v2 <- c(1,1) I want to keep c(3,5,7,7) from v1. Now v1[-match(v2, v1)] returns [1] 1 3 5 7 7.. Not what I want.

4 Answers

You can use vsetdiff from the "vecsets" library (this will keep the duplicates as opposed to setdiff), in the following way:

library(vecsets)
v1 <- c(1,1,3,5,7,7)
v2.1 <- c(3,5)
> vsetdiff(v1, v2.1)
[1] 1 1 7 7
v2.2 <- c(1,7)
> vsetdiff(v1, v2.2)
[1] 1 3 5 7
v2.3 <- c(1,1)
> vsetdiff(v1, v2.3)
[1] 3 5 7 7
Reduce(function(x, y) x[-match(y, x)], v2, init = v1)

There's probably a better way using a truly recursive function, but I think you could accomplish this with a for loop:

v1 <- c(1, 1, 3, 5, 7, 7)
v2 <- c(1,1)
v1_keep <- v1

for (i in seq_along(v2)){
  v1_keep <- v1_keep[-match(v2[i], v1_keep)]
}

v1_keep
# [1] 3 5 7 7

Using map2

library(purrr)
map2(v1, v2, setdiff) %>% 
     flatten
Related