[R] Sorting based a custom sorting function

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Thu Dec 14 20:30:27 CET 2023


On 14/12/2023 11:37 a.m., Martin Morgan wrote:
> In the spirit of 'advent of code', maybe it is better to exploit the features of the particular language you've chosen? Then the use of factors seems very relevant.
> 
> value_levels <- c("Small", "Medium", "Large")
> df <- data.frame(
>      person = c("Alice", "Bob", "Bob", "Charlie"),
>      value = factor(
>          c("Medium", "Large", "Small", "Large"),
>          levels = value_levels
>      )
> )
> df[with(df, order(person, value)),]
> 
> Likely this is more efficient than the hints of your existing solution, because it will act on vectors rather than iterating through individual elements of the 'person' and 'value' vectors.
> 
> For a more general solution, I don't think I'd follow the low-level approach Duncan suggests (maybe see also ?Math for S3 generics), but rather define a class (e.g., that requires vectors person and value) and implement a corresponding `xtfrm()` method.

I'd agree, in cases where it's feasible to implement one.  But there are 
cases where the pairwise comparison is obvious, while the numeric 
conversion isn't.

A simple one would be a list of string vectors of different lengths, 
where you want to sort lexicographically.

Duncan

> 
> Have fun with the remainder of the advent!
> 
> Another Martin
> 
> From: R-help <r-help-bounces using r-project.org> on behalf of Martin Møller Skarbiniks Pedersen <traxplayer using gmail.com>
> Date: Thursday, December 14, 2023 at 6:42 AM
> To: R mailing list <r-help using r-project.org>
> Subject: Re: [R] Sorting based a custom sorting function
> On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch <murdoch.duncan using gmail.com> wrote:
>>
> 
>> class(df$value) <- "sizeclass"
>>
>> `>.sizeclass` <- function(left, right) custom_sort(unclass(left),
>> unclass(right)) == 1
>>
>> `==.sizeclass` <- function(left, right) custom_sort(unclass(left),
>> unclass(right)) == 0
>>
>> `[.sizeclass` <- function(x, i) structure(unclass(x)[i], class="sizeclass")
>>
>> df[order(df$value),]
>>
>> All the "unclass()" calls are needed to avoid infinite recursion.  For a
>> more complex kind of object where you are extracting attributes to
>> compare, you probably wouldn't need so many of those.
> 
> Great! Just what I need. I will create a class and overwrite > and ==.
> I didn't know that order() used these exact methods.
> 
> My best solution was something like this:
> 
> quicksort <- function(arr, compare_func) {
>    if (length(arr) <= 1) {
>      return(arr)
>    } else {
>      pivot <- arr[[1]]
>      less <- arr[-1][compare_func(arr[-1], pivot) <= 0]
>      greater <- arr[-1][compare_func(arr[-1], pivot) > 0]
>      return(c(quicksort(less, compare_func), pivot, quicksort(greater,
> compare_func)))
>    }
> }
> 
> persons <- c("alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf",
>               "hotel", "india", "juliett", "kilo", "lima", "mike", "november",
>               "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform",
>               "victor", "whiskey", "x-ray", "yankee", "zulu")
> 
> quicksort(persons, function(left, right) {
>    nchar(left) - nchar(right)
> })
> 
> Regards
> Martin
> 
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list