2011-11-07 154 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 ; 
    } 
} 
相关问题