読者です 読者をやめる 読者になる 読者になる

An alternative of the base:setdiff(x, y) for list objects

R English

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)