I need to replicate the following sorting behavior (found in Python) in R.
Assuming In Python:
l = [(0,0), (1,-1), (-1,0), (-1,-1)]
>>> sorted(l)
[(-1, -1), (-1, 0), (0, 0), (1, -1)]
>>> min(l)
[(-1, -1)]
The equivalent data structure in R is:
l <- list(c(0,0), c(1,-1), c(-1,0), c(-1,-1))
The sort()
and sort.list()
methods are not implemented for non-atomic vectors.
In my use-case I can guarantee a list of length 2 vectors, so this works:
sorted <- function(list){
m=matrix(unlist(list), ncol = 2, byrow = T)
asplit(
m[order(m[,1],m[,2]),],
1
)
}
Replicating the behavior of min
from Python is easy, just relies on the correct function of a sorted
implementation in R.
min.list <- function(list) sorted(list)[1]
Advice on implementing the same behavior as sorted
is greatly appreciated, and considerations for efficiency are especially welcomed.
Unnecessary for my implementation, but an additional consideration is the sorted
behavior when the sub-lists varies in length.
>>> sorted([(0,0), (1,1), (0,-1), (0,-1, 0), (0,-1,-1), (0, 0, 0)])
[(0, -1), (0, -1, -1), (0, -1, 0), (0, 0), (0, 0, 0), (1, 1)]
Thanks in advance
CodePudding user response:
Maybe we can try this way
> l <- list(c(0, 0), c(1, 1), c(0, -1), c(0, -1, 0), c(0, -1, -1), c(0, 0, 0))
> l[order(sapply(l, toString))]
[[1]]
[1] 0 -1
[[2]]
[1] 0 -1 -1
[[3]]
[1] 0 -1 0
[[4]]
[1] 0 0
[[5]]
[1] 0 0 0
[[6]]
[1] 1 1
CodePudding user response:
One option is to row bind to a matrix, split by column and use order()
to get the indices. For ragged data, it's necessary to standardize the lengths first but obviously this step can be skipped for slightly increased efficiency if the data is guaranteed to be of equal length.
l <- list(c(0, 0), c(1, 1), c(0, -1), c(0, -1, 0), c(0, -1, -1), c(0, 0, 0))
l[do.call(order, c(asplit(do.call(rbind, lapply(l,
`length<-`, max(lengths(l)))), 2), na.last = FALSE))]
[[1]]
[1] 0 -1
[[2]]
[1] 0 -1 -1
[[3]]
[1] 0 -1 0
[[4]]
[1] 0 0
[[5]]
[1] 0 0 0
[[6]]
[1] 1 1