2次元配列のソートについて


umo  2003-11-27 18:20:31  No: 52652  IP: [192.*.*.*]

初めて質問させて頂きます。
至らない点がありましたらご指摘お願いいたします。

行いたいことは 2次元配列の『列』でのソートです。
Excelのように列にてソートを行いたく思います。

まずファイルから vector<string> にて分割を行い、
index を作成し、ソートを行ってみました。

-- ソース --
int main() {

  typedef vector<string> row_type;
  vector<row_type> data;

  ifstream file("c:\\data.csv");
  if ( !file.is_open() ) { return 1; }

  string line;
  while ( std::getline(file, line) ) {
    row_type row;
    
    string::size_type begin = 0;
    string::size_type end = 0;

    const string delim = ",\t";
    while ( (begin = line.find_first_not_of(delim, end)) 
              != string::npos ) {
      end = line.find_first_of(delim, begin);
      row.push_back(line.substr(begin, end-begin));
    }
    data.push_back(row); 
  }

  cout << "元のデータ" << endl;

  string::size_type i,j;
  for ( i = 0; i < data.size(); i++ ) {
    for ( j = 0; j < data[i].size(); j++ ) {
      std::cout << '[' << data[i][j] << "]  ";
    }
    std::cout << std::endl;
  }

// index 作成
  int index[65535];   // vector<string>.size() にしたい。
  int counter = 0;
  for (counter = 0; counter < data.size(); ++counter){
    index[counter] = counter;
  }

/* ----- ここからが問題 ----- */
  
// ソートの実行
  string str;
  string::size_type tempval = 0;

  for (i = 0; i < data.size(); i++){
    str = data[index[i]][2];
    int x = i;
    
    for (j = 0 ; j < data.size() ; j++){
      if (strcmp(data[index[j]][2].c_str(), 
                                str.c_str()) > 0){
        str = data[index[j]][2];
        x = j;
      }
    }

// インデックスの交換
  tempval = index[i];
  index[i] = index[x];
  index[x] = tempval;
  }

// 出力
  cout << "変換後のデータ" << endl;

  for (i = 0; i < data.size(); i++){
    cout << index[i] << "" ;
    for (j = 0; j < data[i].size(); j++){
      cout << '[' << data[index[i]][j] << "]";
    }
    cout << endl;
  }
  return 0;
}

-- data.csv -- 
"1","2000/01/01","test"
"2","2000/01/02","test2"
"3","2000/01/03","test3"
"4","2000/01/04","test"
"5","2000/01/05","test2"
"6","2000/01/06","test3"
"7","2000/01/07","test4"

-- 変換後 --
1["2"]["2000/01/02"]["test2"]
2["3"]["2000/01/03"]["test3"]
3["4"]["2000/01/04"]["test"]
4["5"]["2000/01/05"]["test2"]
5["6"]["2000/01/06"]["test3"]
0["1"]["2000/01/01"]["test"]
6["7"]["2000/01/07"]["test4"]

上記を実行するとデータがばらばらでまったくソートがされて
おりません。

非常にわかりにくい質問で申し訳ありません。
また非常にみなさんに失礼な質問かもしれません。
申し訳ありませんがヒントだけでも結構です。
アドバイス頂けますでしょうか。

環境は Windows2000, VC6.0にて作成を行っております。
よろしくお願いいたします。

編集 削除
YuO  2003-11-27 18:46:00  No: 52653  IP: [192.*.*.*]

> 行いたいことは 2次元配列の『列』でのソートです。
> Excelのように列にてソートを行いたく思います。
> まずファイルから vector<string> にて分割を行い、
> index を作成し、ソートを行ってみました。

vector<string>ではなく,
struct {
    std::string index;
    std::string date;
    std::string str;
} row_type;
を使った方がわかりやすいのでは?
まぁ,std::vector<std::string>を相手にしても同じようなことができますが。

とりあえず,構造体を利用するとして,まずは比較用の型を用意。
struct row_type_compare : binary_function<row_type, row_type, bool>
{
    bool operator() (const row_type & lhs, const row_type & rhs) const
    {
        return lhs.str < rhs.str; // std::stringは直接比較可能
    }
};

で,
> // ソートの実行
>     string str;
>     string::size_type tempval = 0;

>     for (i = 0; i < data.size(); i++){
>         str = data[index[i]][2];
>         int x = i;
>         
>         for (j = 0 ; j < data.size() ; j++){
>             if (strcmp(data[index[j]][2].c_str(), 
>                                 str.c_str()) > 0){
>                 str = data[index[j]][2];
>                 x = j;
>             }
>         }

> // インデックスの交換
>     tempval = index[i];
>     index[i] = index[x];
>     index[x] = tempval;
>     }

std::sort(data.begin(), data.end(), row_type_compare());
で一発。

インデックスが必要なら,それなりにデータ構造を変える必要がありますが……。

編集 削除
umo  2003-11-27 19:09:12  No: 52654  IP: [192.*.*.*]

YuOさん早速のご返答ありがとうございます。

>vector<string>ではなく,
>struct {
>    std::string index;
>    std::string date;
>    std::string str;
>} row_type;
>を使った方がわかりやすいのでは?

言葉が足りませんでした。申し訳ありません。
構造体にしないのは、data.csvは上記の3つのデータのみではなく、
可変長なデータでした。
よってstd::vector<std::string>にて動的配列を使用しています。

編集 削除
YuO  2003-11-27 21:13:20  No: 52655  IP: [192.*.*.*]

やることは変わらないと思いますが……。
比較用のファンクタクラス作って,std::sortに渡すだけ……。

http://www005.upp.so-net.ne.jp/episteme/html/stlprog/index.html
のところの,
http://www005.upp.so-net.ne.jp/episteme/html/stlprog/_05.html#algo_sort
とか
http://www005.upp.so-net.ne.jp/episteme/html/stlprog/_04.html#making_fun
を参照してみてください。

編集 削除
umo  2003-11-28 00:17:52  No: 52656  IP: [192.*.*.*]

YuOさんありがとうございます。
まだファンクタクラス等への理解がありませんので、
YuOさんの適切なご指示を理解できません。

早速、『Effective STL』をAmazon にて購入しました。
勉強せねばと思います。

結果、私には回答が導きだせませんでした。
しかしYuOさんほどの著名なかたが、私ごときの質問に回答いただき、
とても幸せに思います。ありがとうございました。

編集 削除
umo  2003-11-28 00:27:52  No: 52657  IP: [192.*.*.*]

以下書き方が良くないですね・・。

> 結果、私には回答が導きだせませんでした。

"私に回答を導きだすのには時間が必要です。" に変更させてください。

編集 削除