2016-06-07 120 views
3

我有一個自定義類對象(元組列表)。 我也已經定義了<.myclass>.myclass==.myclassR中自定義類的元素列表的排序列表?

現在我有一個

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)) 

我要排序L,對指數1即我已經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' 

有沒有解決這個問題?一般來說,根據比較運算符的自定義定義,我是否可以擁有排序,最小等功能?

編輯:繼或許有助於瞭解結構更好: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) 
} 

現在我想所需的Llist(list(c,_,_),list(b,_,_),list(a,_,_))

+1

「我想在obj1上排序L」。這意味着什麼含糊不清。請提供可重複的示例並顯示預期輸出。 – Roland

+0

我澄清了一下。我希望它不再含糊不清。基本上我想排序第一個索引,(這是對我的類的對象),爲此我有一個比較運算符實現。 – Hrishikesh

+0

請通過提供一個可重現的例子*來澄清。 – Roland

回答

2

This answer準確地說明了在class編輯對象上應用定製的sort所需要的。正如羅蘭所指出的那樣,您實際上需要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/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功能看起來像toList = function(x) x[[1L]]

+0

謝謝,我看到了答案,但我無法得到適當的'''''定義。隨着你的定義,它的工作。 (我不完全清楚''['函數)的目的是什麼。無論如何,我最終更喜歡quicksort解決方案,因爲我有清單列表,並且我可以指定哪些索引來排序等,它只是給了我更多的自由(而且似乎是「更乾淨」的方法,而不是創建更多的類) – Hrishikesh

+0

@ Hrishikesh:進行編輯以解決按指定索引排序的選項。就我個人而言,我發現使用「class」es + R的已有泛型函數比使用更多函數重新構建R的功能更清潔。在這裏,僅指定一些'Ops'和''[''''方法,'sort' /'order' /'xtfrm' /'rank'和它們的包裝器都可以適用於該對象。此外,上述功能可以改變,以適應實際的「L」結構。 –

0

我想利用內部並認爲更有效的排序,但似乎沒有這種類型的設備可以自定義比較運算符。因此,我最終使用quicksort的實現來對任意索引處的列表進行排序,假定該索引處的元素之間存在比較。

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")這似乎有一大堆的名單上實現的功能。來自Aaron的