Search code examples
rlistsortingcoerce

Coercing List of List Individual Elements to Vector Type


I'm using the permn function from CRAN package combinat to produce a list of lists composed of all the permutations of a range of numbers as follows

x <- str(permn(3))
x

List of 6
$ : int [1:3] 1 2 3
$ : int [1:3] 1 3 2
$ : int [1:3] 3 1 2
$ : int [1:3] 3 2 1
$ : int [1:3] 2 3 1
$ : int [1:3] 2 1 3

I also have

typeof(x[[1]])
"integer"

My goal is to sort this list of lists in ascending numerical order (each element needs to be treated as a three digit number), and while the following works correctly

permn(3)->x
x[order(sapply(x,'[[',1))]
[[1]]
[1] 1 2 3

[[2]]
[1] 1 3 2
...

any permn(n) n>3 yields an incorrect sorting. I realize that my issue is that I am sorting on individual values rather than n digit numbers, but I can't figure out how to decompose, sort, and then recompose correctly. I've tried

function(n){
out <-list()
permn(n)->list.of.lists
for(i in 1:length(list.of.lists)){
out[[length(out)+1]] <- unlist(list.of.lists[i])
}
out

but it gives the same results as

x[order(sapply(x,'[[',1))]

namely, I don't have each element ordered in the context of the other elements I'm working with.

Any suggestions?


Solution

  • I wasn't able to find a permn-package in CRAN. And I wasn't able to find a permn function in package:perm, so I'm not able to reproduce you results.

    If x is a list, then x[1] will also be a list, so your efforts with typeof(x[1]) are not telling you what the first element is. You should be using typeof(x[[1]] if you want to see what is in the first sublist of x. The print output shows you it is a list of integer vectors. If you want a list of vectors sorted, then use:

     lapply( x, sort)
    

    The suggestion to use sapply will return a matrix. I'm assuming that you are using permn just to create an example since as I understand your request, it would be to produce the same result as rep(list(1,2,3), 6).

    If you want these paste()-d together as the basis of the sort/order operation then use:

    x[ order( sapply(x, paste0, collapse=".")) ]
    

    or, more efficiently, avoiding type coercion (although more verbose)

    x[order(vapply(x, function(y) sum(y * 10^((length(y)-1L):0)), numeric(1)))]
    

    or pull the multiplier out first,

    mult <- 10^((length(x[[1]])-1L):0)
    x[order(vapply(x, function(y) sum(y * mult), numeric(1)))]