Using the base::unique(x), the base::setdiff(x, y) has the same problem as follow:
> unique(list(a=1,b=2,c=3,a=1)) [[1]] [1] 1 [[2]] [1] 2 [[3]] [1] 3
So, I wrote an alternative of the base::setdiff(x, y) function, too.
lsetdiff <- function(x, y) { xclass <- class(x) yclass <- class(y) if (xclass != yclass) stop("x and y must be the same class") class(x) <- "" class(y) <- "" if (!is.list(x)) stop("x must be a list") if (!is.list(y)) stop("y must be a list") if (!is.null(names(x))) nx <- names(x) else nx <- rep("", length(x)) nvx <- paste(nx, ",", as.character(x)) if (!is.null(names(y))) ny <- names(y) else ny <- rep("", length(y)) nvy <- paste(ny, ",", as.character(y)) x <- lunique( if (length(x) || length(y)) { x[match(nvx, nvy, 0L) == 0L] } else { x } ) class(x) <- xclass x } l1 <- list(a=1, b="x", c=c("xxx", "djfk"), d=list(y=1,x=2,z=3), e=matrix(c(1,1,1,1), ncol=2)) l2 <- list(a=1, b="x", c=c("xxx", "djfk"), d=list(y=1,3), e=matrix(c(1,1,1,1), ncol=2)) lsetdiff(l1, l2)
The lsetdiff(x, y) returns "a named list" that has elements that have different values in the x and y.
> lsetdiff(l1, l2) $d $d$y [1] 1 $d$x [1] 2 $d$z [1] 3
Another set operations for list objects as follow
The lunion(x, y)
lunion <- function(x, y, allowSameName = TRUE) { xclass <- class(x) yclass <- class(y) if (xclass != yclass) stop("x and y must be the same class") class(x) <- "" class(y) <- "" if (!is.list(x)) stop("x must be a list") if (!is.list(y)) stop("y must be a list") lunique(c(x, y), allowSameName) } l1 <- list(a=1, b="x", c=c("xxx", "djfk"), d=list(y=1,x=2,z=3), e=matrix(c(1,1,1,1), ncol=2)) l2 <- list(a=1, b="x", c=c("xxx", "djfk"), d=list(y=1,3), e=matrix(c(1,1,1,1), ncol=2)) lunion(l1, l2)
The lintersect(x, y)
lintersect <- function(x, y) { xclass <- class(x) yclass <- class(y) if (xclass != yclass) stop("x and y must be the same class") class(x) <- "" class(y) <- "" if (!is.list(x)) stop("x must be a list") if (!is.list(y)) stop("y must be a list") if (!is.null(names(x))) nx <- names(x) else nx <- rep("", length(x)) nvx <- paste(nx, ",", as.character(x)) if (!is.null(names(y))) ny <- names(y) else ny <- rep("", length(y)) nvy <- paste(ny, ",", as.character(y)) lunique(y[match(nvx, nvy, 0L)]) } l1 <- list(a=1, b="x", c=c("xxx", "djfk"), d=list(y=1,x=2,z=3), e=matrix(c(1,1,1,1), ncol=2)) l2 <- list(a=1, b="x", c=c("xxx", "djfk"), d=list(y=1,3), e=matrix(c(1,1,1,1), ncol=2)) lintersect(l1,l2)