2011-11-07 153 views
3

我有一個列表的集合,每個列表包含大約6到7個值。像,根據索引和優先級對列表數進行排序

list1 = 2,4,7,4,9,5 
list2 = 4,3,7.3,9,8,1.2 
list3 = 2,2.4,7,9,8,5 
list4 = 9,1.6,4,3,4,1 
list5 = 2,5,7,9,1,4 
list6 = 6,8,7,2,1,5 
list7 = 4,2,5,2,1,3 

現在我想排序這些與索引1作爲主要和索引3作爲輔助和索引2作爲第三等等。也就是說,輸出應該是這樣的:

2,2.4,7,9,8,5 
2,4,7,4,9,5 
2,5,7,9,1,4 
4,2,5,2,1,3 
6,8,7,2,1,5 
9,1.6,4,3,4,1 

我想要的列表順序進行排序的索引1第一,如果值是相同的索引1比排序是在做INDEX3,如果不是索引2進一步相同。這裏的列表數量較少,可以增加到20個,索引也可以增長到20個。

我想知道的算法與iTunes歌曲排序的算法相同,其中首先按相同專輯排序,然後按藝術家排序,然後按排序排序,然後按名稱排序。如果專輯名稱相同,那麼這張專輯的排序是相同的,然後是排序等。代碼可以在C/C++/tcl/shell中。

+0

它真指數2之前INDEX3?如果是的話,那麼在你的解釋中等等就不足以解釋排序謂詞。 –

回答

3
sort -n -t ',' -k 1 -k 3 -k 2 

將列表作爲單獨的行輸入到列表中。

+0

雖然會將數字處理爲字符串或整數嗎? – Rup

+1

@Rup:由於'-n',因此爲浮動。 – jpalecek

+0

sort -n -t','-k 1 -k 3 -k 2正常工作。 – user954134

1

你可以使用STL's sort,然後你所要做的就是編寫一個你想要的比較函數(鏈接中的例子應該足夠好)。

3

爲此在TCL,假設有沒有大量的數據(幾MB不會是「龐大」),最簡單的方法是:

# Read the values in from stdin, break into lists of lists 
foreach line [split [read stdin] "\n"] { 
    lappend records [split $line ","] 
} 

# Sort twice, first by secondary key then by primary (lsort is _stable_) 
set records [lsort -index 1 -real $records] 
set records [lsort -index 0 -real $records] 

# Write the values back out to stdout 
foreach record $records { 
    puts [join $record ","] 
} 

如果你使用什麼更復雜考慮使用Tcllib中的csv包進行解析和格式化,因爲它將處理Real Data中出現的許多語法問題。如果你正在處理大量數據(其中「lot」取決於你部署多少內存),那麼考慮使用更加面向流的方法來處理數據(並且在內存處理中還有一些其他優化)而且您可能還想使用-command選件lsort來提供自定義比較器,因此您只能排序一次;自定義比較器的性能受到很大影響,唉,但是對於許多記錄而言,比較次數的減少會勝出。或者將數據推送到SQLite或Postgres等數據庫中。

+0

這就是我在第一次做的,但我不需要創建新的文件和存儲在數據結構中並不容易..感謝您的輸入。 :) – user954134

+0

@ user954134:你正在尋找的東西越詳細,你越有可能得到直接有用的東西。特別是說明所需的數據源和接收器以及要處理多少數據,這些都將大有幫助。 (排序1MB和1TB有很大的區別!) –

1

既然你問了一個Tcl的解決方案:

set lol { 
    {2 4 7 4 9 5} 
    {4 3 7.3 9 8 1.2} 
    {2 2.4 7 9 8 5} 
    {9 1.6 4 3 4 1} 
    {2 5 7 9 1 4} 
    {6 8 7 2 1 5} 
    {4 2 5 2 1 3} 
} 

set ::EPS 10e-6 
proc compareLists {ixo e1 e2} { 
    foreach ix $ixo { 
     set d [expr {[lindex $e1 $ix] - [lindex $e2 $ix]}] 
     if {abs($d) > $::EPS} { 
     return [expr {($d>0)-($d<0)}] 
     } 
    } 
    return 0 
} 

foreach li [lsort -command [list compareLists {0 2 1}] $lol] { 
    puts $li 
} 

希望有所幫助。

+0

非常感謝.. :) – user954134

0

這裏是一個C++的解決方案:

#include <iostream> 
#include <vector> 
#include <algorithm> 

template <typename Array, typename CompareOrderIndex> 
struct arrayCompare 
{ 
    private: 
     size_t 
     size ; 
     CompareOrderIndex 
     index ; 
    public: 

     arrayCompare(CompareOrderIndex idx) : size(idx.size()), index(idx) { } 

     bool helper(const Array &a1, const Array &a2, unsigned int num) const 
     { 
     if(a1[ index[size-num] ] > a2[ index[size-num] ]) 
     { 
      return false ; 
     } 

     if(!(a1[ index[size-num] ] < a2[ index[size-num] ])) 
     { 
      if(1 != num) 
      { 
       return helper(a1, a2, num-1) ; 
      } 
     } 

     return true ; 
     } 

     bool operator()( const Array &a1, const Array &a2) const 
     { 
     return helper(a1, a2, size) ; 

     } 
} ; 

int main() 
{ 
    std::vector< std::vector<float> > lists = {  { 2, 4, 7, 4, 9, 5}, 
                { 4, 3, 7.3, 9, 8, 1.2 }, 
                { 2, 2.4, 7, 9, 8, 5 }, 
                { 4, 2, 5, 2, 1, 3 }, 
                { 9, 1.6, 4, 3, 4, 1 }, 
                { 2, 5, 7, 9, 1, 4 }, 
                { 6, 8, 7, 2, 1, 5 }, 
                { 4, 2, 5, 2, 1, 1 }, 
               }; 
    // 
    // Specify the column indexes to compare and the order to compare. 
    // In this case it will first compare column 1 then 3 and finally 2. 
    // 
    //std::vector<int> indexOrder = { 0, 2, 1, 3, 4 ,5 } ; 
    std::vector<int> indexOrder = { 0, 2, 1 } ; 

    arrayCompare< std::vector<float>, std::vector<int>> compV(indexOrder) ; 

    std::sort(lists.begin(), lists.end(), arrayCompare< std::vector<float>, std::vector<int>>(indexOrder) ) ; 

    for(auto p: lists) 
    { 
     for(unsigned int i = 0; i < p.size(); ++i) 
     { 
      unsigned int idx = (i > (indexOrder.size() -1) ? i : indexOrder[i]) ; 

      std::cout << p[idx] << ", " ; 
     } 
     std::cout << std::endl ; 
    } 
} 
相關問題