あるベクトルから別のベクトルの要素を引いたベクトルを求める

差集合(setdiff)ではない。たとえば、

x <- c(1, 3, 1, 2, 2, 3, 3, 3, 5, 8 )
y <- c(1, 1, 2, 5)

この2つのベクトルに対しその操作をした結果、

[1] 2 3 3 3 3 8

というような出力が欲しい。これくらいのものありそうな気もするけど見つけられなかった。
でも似たようなの最近どこかで見たなと思いつつ検索していたら…

またおm(ry
というわけで参考にしながら書いた。

mydiff <- function(x, y){
  tmp      <- intersect(names(table(x)), names(table(y)))
  result.t <- c(table(x)[tmp] - table(y)[tmp],
                table(x)[setdiff(names(table(x)), tmp)])
  result   <- rep(names(result.t), result.t)
  ifelse(is.numeric(c(x,y)),
         return(as.numeric(result)),
         return(result))
}

実行例

> x <- c(1, 3, 1, 2, 2, 3, 3, 3, 5, 8 )
> y <- c(1, 1, 2, 5)
> z <- c(1, 1, 1, 2, 2, 5)
> mydiff(x, y)
[1] 2 3 3 3 3 8
> mydiff(z, y)
[1] 1 2
> a <- c("b", "d", "c", "e", "a", "e", "e", "c")
> b <- c("e", "c", "a", "c")
> mydiff(a, b)
[1] "e" "e" "b" "d"
> mydiff(b, a)
Error in rep(names(result), result) : invalid 'times' argument

y⊆xかつyのどの要素の個数も対応するxの要素の数を超えてはいけない。そうじゃないとrepのところでエラーがでる。ただもともと欲しかったものから考えると望ましい挙動なのでこれでよしとする。
これはProject EulerのProblem 88を考えていたら欲しくなった。欲しくなったからといってこれを使えば解けるとも限らないんだけど。もうずいぶんハマってるし…。