コンテナ内の順番で別コンテナをソート

[戻る]
ハノイ 2006/12/21(木) 14:29:30
WinXP(SP2) VC++ 6.0です。
STLはさわりはじめたばかりです。
struct student {
  int student_no;
  int point;
   
  bool operator<(const student& r) const {
    return point < r.point;
  }
};
typedef std::set<student> student_set_t;
student_set_t student_set;

として、student_noに一意の生徒番号、pointに得点を次々とinsertしていき得点順に
ソートしておきます。
ここまではできました。

その後、{1,2,3,4,5}など任意の数の生徒番号が入ったvectorを渡すと、student_set内
でソートされた順にvector要素がソートされて返ってくるような処理を書きたいのです
が、どう手をつけていいのかからわかりません。

よくありそうな処理なので、STLを使えばうまくかけるのかなあと思っている程度なの
で、ほかにもっとよい方法などあれば教えていただきたいです。

επιστημη [HomePage] 2006/12/21(木) 15:25:02
/*
 * 説明は省略
 */

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

struct student {
  int no;
  int point;
};

bool no_less(const student& x, const student& y) 
{ return x.no < y.no; }

bool point_less(const student& x, const student& y) 
{ return x.point < y.point; }

struct no_eq {
  int no;
  no_eq(int n) : no(n) {}
  bool operator()(const student& x) const {
    return x.no == no;
  }
};

int get_no(const student& x) 
{ return x.no; }

int main() {
  student master[8] = { 
    {7, 345},
    {8, 678},
    {1, 123},
    {2, 456},
    {5, 567},
    {6, 812},
    {3, 781},
    {4, 234},
  };

  std::vector<student> record(master, master+8);

  int no[5] = { 4, 5, 3, 1, 2};
  std::vector<int> target(no, no+5);

  // ----- ここから
  std::vector<student> work;
  for ( std::vector<int>::iterator i = target.begin(); i != target.end(); 
++i ) {
    std::vector<student>::iterator item = std::find_if(record.begin(), 
record.end(), no_eq(*i));
    if ( item != record.end() ) {
      work.push_back(*item);
    }
  }

  std::sort(work.begin(), work.end(), &point_less);
  std::transform(work.begin(), work.end(), target.begin(), &get_no);
  // ----- ここまで

  for ( std::vector<int>::iterator i = target.begin(); i != target.end(); 
++i ) {
    std::cout << *i << ' ';
  }
  std::cout << std::endl;
}

επιστημη [HomePage] 2006/12/21(木) 15:53:43
…違うな。題意に沿うのはこっち。

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

struct keyed_less {
  std::map<int,int>& ref;
  keyed_less(std::map<int,int>& r) : ref(r) {}
  bool operator()(int x, int y) const {
    return ref[x] < ref[y];
  }
};

int main() {
  int master[] = { 
    7, 345,
    8, 678,
    1, 123,
    2, 456,
    5, 567,
    6, 812,
    3, 781,
    4, 234,
  };

  std::map<int,int> record;
  for ( int i = 0; i < 8; ++i ) {
    record[master[i*2]] = master[i*2+1];
  }

  int no[5] = { 4, 5, 3, 1, 2};
  std::vector<int> target(no, no+5);
  std::sort(target.begin(), target.end(), keyed_less(record));

  for ( int i = 0; i < target.size(); ++i ) {
    std::cout << target.at(i) << '/' 
              << record[target.at(i)] << std::endl;
  }
  std::cout << std::endl;
}

ハノイ 2006/12/21(木) 19:39:04
[[解決]]
1つめのはいまいち理解できていませんが、2つめのは分かりやすく、目からうろこがお
ちる思いでした。
必ずしも、ソートしたものを持っておく必要はないわけですね。
それにしてもこんなに簡潔に書けるなんて、STLって奥が深そうです..
どうもありがとうございました。

古いスレッドには追加発言できません。