对R中自定义类的元素列表进行排序?

时间:2016-06-07 10:15:49

标签: r list sorting comparator

我有一个自定义类对象(元组列表)。 我也在其上定义了<.myclass >.myclass==.myclass

现在我有一个

a <- obj1 # of myclass
b <- obj2 # of myclass
c <- obj3 # of myclass
L <- list(list(a,12,1),list(b,215,23),list(c,21,9))

我想在索引1上排序L,即我有b < c < a然后,我希望以这种形式排序L list(list(b,215,23),list(c,21,9),list(a,12,1))

我如何实现这一目标?

在我的搜索中,我找到了如何对特定索引进行排序,并使用它编写了以下函数

magic_sort <- function(lst, sortind, dec = T) {
    return(lst[order(sapply(lst,'[[',sortind), decreasing = dec)])
}

但是当我给它索引1时,要对obj1进行排序,它会失败并带有

> magic_sort(L,1)
Error in order(sapply(lst, "[[", sortind), decreasing = dec) : 
    unimplemented type 'list' in 'orderVector1'

有没有解决这个问题?一般来说,我可以根据比较运算符的自定义定义来实现sort,minimum等函数吗?

编辑:以下可能有助于更好地理解结构:http://pastebin.com/0M7JRLTu

编辑2:

library("sets")

a <- list()
class(a) <- "dfsc"
a[[1]] <- tuple(1L, 2L, "C", "a", "B")

b <- list()
class(b) <- "dfsc"
b[[1]] <- tuple(1L, 2L, "A", "b", "B")

c <- list()
class(c) <- "dfsc"
c[[1]] <- tuple(1L, 2L, "A", "a", "B")

L <- list()
L[[1]] <- list(a, 12, 132)
L[[2]] <- list(b, 21, 21)
L[[3]] <- list(c, 32, 123)

`<.dfsc` <- function(c1, c2) {
    return(lt_list(toList(c1),toList(c2)))
}

`==.dfsc` <- function(c1, c2) {
    return(toString(c1) == toString(c2))
}

`>.dfsc` <- function(c1, c2) {
    return(!((c1 < c2) || (c1 == c2)))
}

lt_list <- function(l1, l2) {
    n1 <- length(l1)
    n2 <- length(l2)
    j = 1
    while(j <= n1 && j <= n2) {
        if (l1[[j]] != l2[[j]]) {
            return (l1[[j]] < l2[[j]])
        }
        j = j + 1
    }
    return(n1 < n2)
}

toString.dfsc <- function(x) {
    code_string <- ""
    #for(ii in x[[1]]) {
    for(ii in x) {   
        code_string <- paste(code_string,"(",ii[[1]],",",ii[[2]],",",ii[[3]],",",ii[[4]],",",ii[[5]],")", sep = "")
    }
    return(code_string)
}

现在我想要L所需的list(list(c,_,_),list(b,_,_),list(a,_,_))

2 个答案:

答案 0 :(得分:2)

来自Aaron的

This answer确切地说明了在sort ed对象上应用自定义class所需的内容。正如Roland所说,你实际上需要sort“L”,因此,这就是关注自定义sort的地方。为了灵活地指定“L”元素的索引到sort,一种方法是在“L”上存储额外的attr

将“L”转换为适当的对象:

class(L) = "myclass"
attr(L, "sort_ind") = 1L
需要定义

Ops个方法(提取数据的相关元素):

"<.myclass" = function(x, y) 
{
    i = attr(x, "sort_ind") ## also check if 'x' and 'y' have the same 'attr(, "sort_ind")'
    x[[1]][[i]] < y[[1]][[i]] 
}
"==.myclass" = function(x, y) 
{
     i = attr(x, "sort_ind")
     x[[1]][[i]] == y[[1]][[i]] 
}
">.myclass" = function(x, y) 
{
    i = attr(x, "sort_ind")
    x[[1]][[i]] > y[[1]][[i]] 
}

一个子集方法:

"[.myclass" = function(x, i) 
{
    y = .subset(x, i)
    attributes(y) = attributes(x)
    return(y)
}

由于对"<" / sort的调用将最终调用需要{{1}的order,因此上述方法是必要的(可能除了rank之外)。为了相应地对每个元素进行子集并进行比较。 最后,酱油的获取/设定功能:

.gt

sort_ind = function(x) attr(x, "sort_ind")
"sort_ind<-" = function(x, value) 
{
    attr(x, "sort_ind") = value
    return(x)
}

还可以创建order(L) #[1] 3 2 1 sort_ind(L) = 3 order(L) #[1] 2 3 1 的方法来包装以上所有内容:

sort

(我假设您的sort.myclass = function(x, sort_ind = attr(x, "sort_ind"), ...) { sort_ind(x) = sort_ind NextMethod() } sort(L) sort(L, sort_ind = 1) 函数看起来像toList}

答案 1 :(得分:0)

我想利用内部和所谓的更有效的排序,但似乎没有这种方法可以采用自定义比较运算符。因此,我最终使用快速排序的实现来对任意索引处的列表进行排序,假设该索引处的元素之间存在比较。

part_qsort <- function(l, idx, low, high) {
    lst <- l
    pivot <- lst[[high]][[idx]]
    i <- low - 1

    for(j in low:(high-1)) {
        if ((lst[[j]][[idx]] < pivot) || (lst[[j]][[idx]] == pivot)) {
            i <- i + 1
            swap(lst[[i]],lst[[j]])
        }
    }
    swap(lst[[(i+1)]],lst[[high]])
    eval.parent(substitute(l <- lst))
    return(i+1)
}

# recursive calls to quicksort
qsort <- function(l,idx,low,high) {
    if (low < high) {
        lst <- l
        pi <- part_qsort(lst,idx,low,high)
        qsort(lst, idx, low, pi-1)
        qsort(lst, idx, pi+1, high)
        eval.parent(substitute(l <- lst))
    }
}

要研究的另一件事可能是library("rlist"),它似乎在列表上实现了一堆功能。