2011-11-07 11 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 

は今、私は三次と二次のようにしてINDEX2として、プライマリおよびindex3とindex1のでこれらをソートしたいです。私は、リストの順序はindex1の最初と値がソートがindex3上とINDEX2よりもさらに同じ場合に行われるよりも、index1のために同じである場合のためにソートされたい

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 

:つまり、出力は次のようにする必要があります。ここでは、リストの数が少なくて20まで増やすことができ、インデックスも20まで増やすことができます。

私が知りたいアルゴリズムは、iTunesのソングソートと同じです。同じソングのソングが最初にソートされ、アーティストがソートされ、その後にランク付けされ、次にソートされます。これは、アルバム名が同じであればソートはアーティストの場合は同じ、次にランクの順で行われます。コードはC/C++/tcl/shellにあります。

+0

はそれが本当にインデックス2の前にindex3されますか?はいの場合、あなたの説明の中で、ソート述語を説明するのに十分ではありません。 –

答えて

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

リストを個々の行として入力します。あなたはより多くの何も複雑なを使用している場合

# 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 ","] 
} 

:大量のデータ(数MBは「巨大」ではないでしょう)最も簡単な方法のようになりますが、そこではありませんと仮定すると、Tclでこれを行うには

+0

数字は文字列または整数として処理されますか? – Rup

+1

@Rup: '-n'のために浮動小数点として。 – jpalecek

+0

sort -n -t '、' -k 1 -k 3 -k 2は正常に動作します。 – user954134

1

STL's sortを使用することができます。必要な処理を行う比較関数を記述するだけで済みます(リンクの例で十分です)。

3

単純な数字よりも、Real Dataで切り詰める多くの構文上の問題に対処するため、Tcllibのcsvパッケージを解析と書式設定に使用することを検討してください。たくさんのデータを扱う場合(「たくさん」はどこのメモリを配備するかによって決まります)、データを処理するためにストリーム指向の方法を使用することを検討してください(メモリ処理には他にもいくつかの最適化があります) -commandオプションをlsortに使用してカスタムコンパレータを指定して1回だけソートできるようにすることもできます。カスタムコンパレータのパフォーマンスヒットは非常に高いです、しかし、多くのレコードでは、比較回数が減ります。または、データを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 ; 
    } 
} 
関連する問題