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

An alternative of the base:unique(x) for list objects

R English

The base::unique(x) function returns a vector, data frame or array that were removed duplicate elements/rows.
When the x is a list object, the base::unique(x) returns an unnamed list object 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::unique(x) function.

lunique <- function(x, allowSameName = TRUE) {
  xclass   <- class(x)
  class(x) <- ""
  if (!is.list(x)) stop("x must be a list.")
  if (!allowSameName) {
    nnlist <- match(names(x), "", 0L)
    if (!is.null(names(x))) {
      unlist <- match(unique(names(x)), names(x))
      unlist <- replace(rep(0, length(x)), unlist, 1)
      x <- x[(nnlist | unlist) != 0]
    }
  }
  if (!is.null(names(x))) n <- names(x)
  else n <- rep("", length(x))
  nv <- paste(n, ",", as.character(x))
  x  <- x[match(unique(nv), nv)]
  class(x) <- xclass
  x
}

l1 <- list(a=1,a=1,a=2,b="Y",c=c(1,1,1,1), d=list(e=1,f=10))
l2 <- list(1,1,"Y",a=3,a=4,c=c(1,1,1,1), d=list(e=1,f=10))
l3 <- list(1,1,c(7,8),list(1,3,2),1,1,1,2,2,2,3,4,5,6)

lunique(l1)
lunique(l1, allowSameName = FALSE)
lunique(l2)
lunique(l3)


The lunique(x) returns a list that were removed duplicate elements.
When the argument allowSameName = TRUE, the lunique(x) allows same named elements with different values.

> lunique(l1, allowSameName = TRUE)
$a
[1] 1
$a
[1] 2
$b
[1] "Y"
$c
[1] 1 1 1 1
$d
$d$e
[1] 1
$d$f
[1] 10

When the argument allowSameName = FALSE, the lunique(x) deletes same named elements except the first element.

> lunique(l1, allowSameName = FALSE)
$a
[1] 1
$b
[1] "Y"
$c
[1] 1 1 1 1
$d
$d$e
[1] 1
$d$f
[1] 10

When list elements are accessed by name, the first element is returned by default.

> l4 <- list(a = 1, a = 2, a = 3)
> l4$a
[1] 1


Even when the x contain unnamed elements, the lunique(x) can remove duplicate elements.

> lunique(l2)
[[1]]
[1] 1
[[2]]
[1] "Y"
$a
[1] 3
$c
[1] 1 1 1 1
$d
$d$e
[1] 1
$d$f
[1] 10