简体   繁体   中英

Extracting cumulative unique Elements from a list

I have a list:

z <- vector("list", 3)
z[[1]]=c(1,2,3,4)
z[[2]]=c(1,6,2,9)
z[[3]]=c(1,2,3,4,5)

I want to create a column matrix with as many items in the list (3)

A=matrix(0,3,1)

And I want each row of the matrix to contain the cumulative number of unique elements in the Z list that havent been seen before. So for example,

The matrix should populate as:

     [1]
A=[1] 4
  [2] 6
  [3] 7

(4 because each element is new, then 6 because the others have been seen before in z[[1]], and then 7 because 5 is the only new element.)

Does anyone know a good way to do this? I can program it in a very stupid way by looping over the 3 and making a dummy matrix and doing unique and testing with if conditions, but it seems a bit excessive.

Thanks for your time.

I think you need to use something that will allow you to loop iteratively, so I'm using a for loop here. We get all the unique elements and for each element in z we sum the values that are in the unique elements and then remove them for the next iteration...

#  Get unique elements
elems <- unique( unlist( z ) )

#  Pre allocate result vector
tot <- numeric(length(z))

for( i in 1:length(z) ){
    # How many unique elements are in this list element
    tot[i] <-  sum( z[[i]] %in% elems )
    #  Remove them from the list so they are not counted in the next iteration
    elems <- elems[ ! elems %in% z[[i]] ]       
  }

#  Get the cumulative sum
cumsum( tot )
[1] 4 6 7

If performance is not really an issue, you can do the following. I can see it being taxing if the list / vectors are very long

test = matrix(data = 0,ncol = 1,nrow=length(z))

for (i in 1:length(z)){
  test[i,1]=length(unique(Reduce(c,z[1:i])))
}

test
     [,1]
[1,]    4
[2,]    6
[3,]    7

Perhaps an unnecessarily complicated way of doing things, but you could use a recursive function.

z <- vector("list", 3)
z[[1]]=c(1,2,3,4)
z[[2]]=c(1,6,2,9)
z[[3]]=c(1,2,3,4,5)

f<-function(x,left=c()) {
  new<-unique(x[[1]][!(x[[1]] %in% left)])
  new.left<-c(new,left)
  if (length(x)==1) return(length(new))
  else return(c(length(new),f(x[-1],left=new.left)))
}
as.matrix(cumsum(f(z)),ncol=1)

     [,1]
[1,]    4
[2,]    6
[3,]    7

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM