Here's a possible solution :
lista=list()
lista[[1]]=c( 1, 2, 4, 6, 8, 9, 10, 11, 12, 19, 32, 34, 35, 36, 37, 38)
lista[[2]]=c(7,8)
lista[[3]]=c(13, 14, 16, 26, 27, 28, 29, 30, 31)
lista[[4]]=c(20, 21, 23, 25, 27, 28, 29, 30)
lista[[5]]=c(9,10,39)
lista[[6]]=c(39,40)
canBeMerged <- function(x,y){
length(intersect(x,y)) > 0
}
mergeFun <- function(x,y){
sort(union(x,y))
}
group <- Reduce(f=function(acc,curr){
# since we wrapped each element inside a list with Map, here we unwrap the current element
currVec <- curr[[1]]
# we search in the accumulated list of "unmergeable" vectors
# if there is one which can be merged with currVec
toMergeIdx <- Position(f=function(x) canBeMerged(x,currVec), acc)
if(is.na(toMergeIdx )){
# none can be merged, let's simply add currVec to the accumulated list
acc[[length(acc)+1]] <- currVec
}else{
# currVec can be merged with the vector at position toMergeIdx, so we merge the
acc[[toMergeIdx]] <- mergeFun(acc[[toMergeIdx]],currVec)
}
return(acc)
},Map(lista,f=list))
Result :
> group
[[1]]
[1] 1 2 4 6 7 8 9 10 11 12 19 32 34 35 36 37 38 39 40
[[2]]
[1] 13 14 16 20 21 23 25 26 27 28 29 30 31
Explanation :
Reduce
uses a binary function to successively combine the elements of a given vector, e.g. given a vector of elements c(1,3,7)
and a binary function +
Reduce(c(1,3,7),f='+')
will call the function one time performing 1+3
(the initial accumulated value of Reduce is the first value, if not specified), then will call the function again passing the current accumulated value 4
and summing it with the next value, computing 4+7
, then finally returns 11
.
Therefore, in this case we want to use Reduce to iterate over the list of vectors and iteratively combining them if they can be merged or keeping them if not.
So, in this case the accumulated value of Reduce, will be a list of "unmergeable" vectors, to be checked and eventually merged to the next vector.
Note that,Since both the accumulated value and the next value of Reduce must be of the same type, we need to wrap every element of lista
in a list using Map
.