• 締切済み

STLのsortで、プライベート変数を比較関数に組み入れたい。

STLのsortで、プライベート変数を比較関数に組み入れたい。 STLのvectorのsortで比較関数を指定してソートをしようとしております。 ソートしようとするvectorは、とあるクラスのプライベート変数であり、 同じクラスの他のプライベート変数を利用した比較を行おうとしています。 例えば int array[4] = {1, 7, 3, 5}; なるプライベート変数があり、比較関数はこんなアルゴリズムとしたいと。 bool compare(int left, int right) { return array[ left ] < array[ right ]; } この compare をクラスのメソッドとして定義して使えるのかなと思っていたのですが コンパイルしたところエラーが出ました。パブリック変数にして、プレディケートの ためのクラスを作って、そこでパブリックメソッドを作って……という方法は見つかった のですが、そのような面倒な方法を経なければいけないのでしょうか。

みんなの回答

回答No.3

 こんばんは。  良し悪しは別にして、恐らくSTLだけでは「for_each」でパラメータ2つのメンバ関数を取り扱う事に無理があるのでは。  「boostライブラリ」の「function」や「bind」を併用した方が手っ取り早いです。  これで良いのかはわかりませんが、以下参考程度に。 #include<vector> #include<algorithm> #include<iostream> #include<boost/bind.hpp> #include<boost/function.hpp> #include<boost/lambda/lambda.hpp> class vectorsorttest { private: int weight[5]; std::vector<int> v; public: vectorsorttest() { int array[ 5 ] = { 1, 0, 2, 4, 3 }; //for(int i = 0 ; i < 5 ; i++) //weight[ i ] = array[ i ]; std::copy(array, array + 5, weight); int member[ 5 ] = { 0, 1, 2, 3, 4 }; //for(int i = 0 ; i < 5 ; i++) //v.push_back( member[ i ] ); v.assign(member, member + 5); //並び替え boost::function<bool(int, int)> fun = boost::bind(&vectorsorttest::compare, this, _1, _2); std::sort(v.begin(), v.end(), fun); //表示 std::for_each(v.begin(), v.end(), std::cout << boost::lambda::_1 << " "); std::cout << std::endl; } bool compare(int left, int right) const { return weight[ left ] < weight[ right ]; } }; int main() { vectorsorttest test; return 0; }

参考URL:
http://www.boost.org
poerno
質問者

お礼

むー、なるほど。なんか、クラスのプライベート変数とプライベートメソッドで実現できて おかしくなさそうな(あくまで感覚根拠)ことができないというのは、結構歯がゆいものが ありますね……。比較メソッドで使う変数をグローバルで用意しておくという方法も、あり っちゃありな気もしてきます。 比較メソッド専用クラスを使った方法もちょっと試してみて、コンパイルが通ったらばまた ご報告させていただきます。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

vectorといっている割には単なる配列を使っていたりと、意味不明なところが多々ありますが... 印象からすると、比較関数を静的メンバ関数にしていないためにエラーが発生しているだけのような気がします。

poerno
質問者

補足

すみません、僕もうまく考えがまとまっていないまま質問をしてしまいました。 以下のようなクラスを考えています。番号とそれに対応する重量のデータがあって、 重量順で vector をソートしたいというものです。 class vectorsorttest { private: int weight[ 5 ]; vector<int> v; public: vectorsorttest() { int array[ 5 ] = { 1, 6, 2, 4, 3 }; for (int i = 0 ; i < 5 ; i++) weight[ i ] = array[ i ]; int member[ 5 ] = { 0, 1, 2, 3, 4 }; for (int i = 0 ; i < 5 ; i++) v.push_back( member[ i ] ); sort(v.begin(), v.end(), compare); } bool compare(int left, int right) { return weight[ left ] < weight[ right ]; } }; これでコンパイルしますと、 error: no matching function for call to ‘sort(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, <unresolved overloaded function type>)’ と出ます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

その「プライベート変数」がどのように定義されているかにもよるんだけど, そのクラスの中で適当なメンバ関数を作ればいけるような気もする. 少なくとも, パブリックにする必要はない.

関連するQ&A

  • Array.sortメソッドのデフォルト比較関数

    JavaScriptのArray.sortメソッドは、 引数を指定しなければデフォルトの比較関数でソートされますが、 この比較関数を取り出して利用できないでしょうか。 要件は、プロパティ[name]と[value]を持ったオブジェクトの配列のソートです。 nameプロパティは半角英数字の文字列で、これをキーにソートしたいと考えています。 ソートの基準は、Array.sortのデフォルトと同じです。 つまり、こんなコードを想定しています。 var ary = [o1, o2, o3]; // o1~o3はそれぞれ上記のオブジェクト ary.sort(function(a, b){ return compare(a.name, b.name); }); このコードにおけるcompare関数を、Array.sortのデフォルト比較関数にしたいのですが、 これは自前で作成するしかないのでしょうか。 数値だけでなく文字列全般の比較になるので、結構実装が面倒そうなのですが、 自作する場合に何か使えそうな標準関数等、無いでしょうか。 今のところ思いついているのは、下記みたいなものです。 var compare = function(a, b) {  var temp = [a, b];  temp = temp.sort();  return temp[0] === a ? -1 : 1; } 比較関数内で更にArray.sortを呼んで2項目をソートし、 順番が入れ替わったかどうかを判定するだけです。 何だか冗長で気持ち悪いコードですので、代案を探しています。

  • STLのvectorで作った配列をメンバ変数にする場合は。。。

    C++初心者です。 STLのvectorで作った配列をメンバ変数は 以下のように宣言し、 class Array { public: vector<int> array; void Set(); } Array::Setのメンバ関数でarrayに値をセットします。 そして、メインからarrayを参照しようとしましたが 値が入っていませんでした。 メンバ変数の宣言の仕方が良くないのですか?

  • クイックソートをC++で作りたいのですが・・・

    題の通り、C++でクイックソートを作りたいのですが、以下のコードではセグメンテーションエラーで動きませんでした。partition関数があやしいと思い、色々と試してみたのですが、やはりできなかったので、質問させていただくことにしました。 結果としては、print関数で昇順に表示出来ればいいのですが・・・。 以下のコードのどこをどう変えれば良いのか、ご指摘の方、何卒よろしくお願い致します。 #include <iostream> #include <vector> using namespace std; class Array { private: vector<int> array; public: void insert( int value ){ array.push_back( value ); } int getSize( ){ return (int)array.size( ); } void quick_sort( ){ quick_sort( 0, (int)array.size( ) - 1 ); } void quick_sort( int left, int right ); int partition( int left, int right ); void swap(int *a,int *b){int tmp=*a;*a=*b;*b=tmp;} void print( ); }; // クイックソートにより配列の添字 left ~ right の部分を整列する関数 void Array::quick_sort( int left, int right ) { if ( left >= right ) { return; } int v = partition( left, right ); quick_sort( left, v - 1 ); quick_sort( v + 1, right ); } //この関数を考える // 配列の添字 left ~ right の部分を,pivot の値より小さい要素と,大きい要素に分割し pivot の位置を返す関数 int Array::partition( int left, int right ) { int i=left; //左からの処理位置 int j=right; //右からの処理位置 int pivot=array[(int)(left+right)/2]; //基準 int tmp=0; while(true){ while(array[i]<pivot){i++;} while(array[j]>pivot){j--;} if(i>=j){return i;} tmp=array[i]; array[i]=array[j]; array[j]=tmp; i++; j++; } } // 配列の内容を表示する関数 void Array::print( ) { for ( int i = 0; i < (int)array.size( ); i++ ) { cout << array[i] << " "; } cout << endl; } int main( ) { Array a1; a1.insert( 56 ); a1.insert( 34 ); a1.insert( 57 ); a1.insert( 64 ); a1.insert( 3 ); a1.insert( 87 ); a1.insert( 85 ); a1.insert( 37 ); a1.insert( 21 ); a1.insert( 4 ); a1.insert( 68 ); a1.insert( 62 ); a1.insert( 42 ); a1.insert( 55 ); a1.insert( 63 ); a1.insert( 95 ); a1.insert( 7 ); a1.insert( 32 ); a1.insert( 78 ); a1.insert( 11 ); cout << "要素数: " << a1.getSize( ) << endl; cout << "ソート前: "; a1.print( ); a1.quick_sort( ); // ここで,ソートを行う関数を呼び出す cout << "ソート後: "; a1.print( ); return 0; }

  • C++でのマージソートの実現方法について

    C++でのマージソートの実現方法について、以下のコードを書いたのですが、どうしてもうまくソートできませんでした。 marge関数がおかしいと思うのですが、自分で確かめてみても、どこがおかしいのか分かりませんでした。 どなたか、どうすればソートされた結果がメイン関数で表示されるようにできるのか教えていただけないでしょうか? #include <iostream> #include <vector> using namespace std; class Array { private: vector<int> array; public: void insert( int value ){ array.push_back( value ); } int getSize( ){ return (int)array.size( ); } void marge_sort( ){ marge_sort( 0, (int)array.size( ) - 1 ); } void marge_sort( int left, int right ); void marge( int left, int middle, int right ); void print( ); }; // マージソートにより配列の添字 left ~ right の部分を整列する関数 void Array::marge_sort( int left, int right ){ if( left >= right ) { return; } int middle = (left + right) / 2; //中央の添字を求める marge_sort( left, middle ); //左の要素が全てバラバラになるまで marge_sort( middle + 1 , right ); //右の要素が全てバラバラになるまで marge( left, middle, right ); //バラバラの要素をソートして併合 } // 個別にソートされた2つの配列(添字 left ~ middle と添字 middle+1 ~ right)を作業用配列を使ってマージする関数 void Array::marge( int left, int middle, int right ) { int num=right-left; int *tmp=new int[num]; int t=0,l=left,r=middle; while(l<middle&&r<right){ if(array[l]<=array[r]){ tmp[t++]=array[l++]; } else { tmp[t++]=array[r++]; } } while(l<middle){ tmp[t++]=array[l++]; } while(r<right){ tmp[t++]=array[r++]; } for(int i=0;i<num;i++){ array[left+i]=tmp[i]; } delete tmp; } // 配列の内容を表示する関数 void Array::print( ) { for ( int i = 0; i < (int)array.size( ); i++ ) { cout << array[i] << " "; } cout << endl; } int main( ) { Array a1; a1.insert( 56 ); a1.insert( 34 ); a1.insert( 57 ); a1.insert( 64 ); a1.insert( 3 ); a1.insert( 87 ); a1.insert( 85 ); a1.insert( 37 ); a1.insert( 21 ); a1.insert( 4 ); a1.insert( 68 ); a1.insert( 62 ); a1.insert( 42 ); a1.insert( 55 ); a1.insert( 63 ); a1.insert( 95 ); a1.insert( 7 ); a1.insert( 32 ); a1.insert( 78 ); a1.insert( 11 ); cout << "要素数: " << a1.getSize( ) << endl; cout << "ソート前: "; a1.print( ); a1.marge_sort(); // ここで,ソートを行う関数を呼び出す cout << "ソート後: "; a1.print( ); return 0; } // 実行結果 要素数: 20 ソート前: 56 34 57 64 3 87 85 37 21 4 68 62 42 55 63 95 7 32 78 11 ソート後: 3 4 34 37 21 42 55 56 57 62 63 7 32 64 68 78 85 87 95 11 ↑のソート後の表示が、昇順にソートされるようにしたいのです。

  • STL vectorの初期化

    STL vectorの初期化についてなんですが 以下のようなクラスのprivateなメンバ変数としてvectorを定義し それをメソッド内のループ処理にて初期化しながら使用したいのですが 初期化の仕方が分かりません。コンストラクタを呼べば初期化されるようですが 以下のようにヘッダとソース内で2度同じような宣言をしてしまっても問題ないのでしょうか? //=== test.h === class test { private : vector<int> array; public : int fnc(); }; //=== test.c === int fnc() { for (int i = 0; i < 10; i++) { //★ここで初期化したい vector<int> array;  ←これで問題ないか? for (int j = 0; j < 10; j++) { array.push_back( md ); } } } C#などでは宣言とインスタンス生成を別に分けられたのですがC++も同様の事が出来るのでしょうか? 一応「array = new vector<int>;」といれて見たのですがエラーが出ました。

  • STLでfind_ifみたいなsortをしたいのですが。

    こんにちは。 STLのdequeのソートで少し複雑な条件でソートしようとしています。 簡単なものでしたら、 sort( m_lists.begin(), m_lists.end(), fnComapreLower ) ; // bool fnComapreLower( lpElem0, sElem1 ) としてソートができますが、fnComapreLowerの比較関数にユーザーパラメータを 与えることはできないのでしょうか ? find_ifなら、 find_if( m_lists.begin(), m_lists.end(), _FINDER_ID( nnn )) ; として構造体を利用できるので便利なのですが、sortにも同様のことはできないのものでしょうか ? find_ifみたいに比較関数の他にユーザーパラメータを与えて処理したいのですが方法が分かりません。 もしご存じの方がいらっしゃいましたら教えていただけないでしょうか。

  • STLのList.sortが上手く使えない

    VC++2005のSTLの、List.sort()を使ってメンバ変数aでソートしたいのですが上手くいきません。 MSDNで"IComparerをオーバーロードしろ"と、書いてあったのを見て、 いろいろ調べて試してはみたのですが、理解不足のため全て失敗しました。 ネットに転がっているサンプルはC#のモノばかりでサッパリです。 調べる手段も分からず八方塞な状態です。どうかお力を貸してください。お願いします。 class TestList { protected: std::list<TestList*> RunList; int a; //この変数でソートする public: MakeList(TestList *test); //リストを"RunList"に登録する }; void main() { TestList Test(); //全てのリストはココに登録 Test->MakeList(new TestList()); Test->MakeList(new TestList()); Test->RunList.sort(); //←ココ。メンバ変数aでソートしたい } 【追記】MSDNの方法では"mscorlib.dll"が必要になります。 もし可能なら違う方法になったとしても、使うことなくソートできるなら、その方が良いです。

  • 関数の引数にSTLを使う

    こんにちは。C++の勉強を最近始めました。 メンバ関数の引数に、STL(queue)を使おうとしています。 以下のように、参照にして使おうと思っています。 int test01::method(queue<int>& q) { return 0; } ですが、コンパイルしようとすると、 「識別子 'queue' がシンタックスエラーを起こしました。」 と言われてエラーになってしまいます・・・。 (他の箇所でqueueを使っていますが、そこではエラーは出ないので、 ヘッダファイルや名前空間はちゃんと指定できていると思います) STLに関する情報を集めてみたのですが、 引数にして使った例を見つけることができませんでした。 シンタックスエラーなので、文法や構文などが正しくないのだと思うのですが、 関数の引数にそもそもSTLを指定できないのか、 コーディングの仕方が間違っているのか、判断ができません。 どのようにしたら、引数に指定できるのでしょうか? ご存知の方がいらしたら、おしえていただきたいです。 よろしくおねがいします。

  • ソート Comparator

    Integer型の変数num(10,4,8,6,9,5)をそれぞれ含むオブジェクト配列aryがあり、それをソートするため Arrays.sort(arry,sortLogic); とした場合、 Comparatorインターフェースを実装したクラスsortLogic内のメソッドで public int compare(Object object1, Object object2) {   return ((ary)object1).compareTo(((ary)object2).num); } とすると、昇順にソート(修正ソートマージ)、また、 return ((ary)object1).compareTo(((ary)object2).num); とすると降順にソートされるみたいなのですが、どのような手順(アルゴリズム)でソートされるのでしょうか?

    • ベストアンサー
    • Java
  • perlで比較関数を使ったソートの仕方

    今、季節をソートするようなプログラムを考えています。 my @array = ('spring','fall','winter','summer'); my @sort = sort number(@array); sub number { if ($a < $b) { return -1; } elsif ($a == $b) { return 0; } elsif ($a > $b) { return 1; } } 実行結果:spring ,summer ,fall ,winter 比較関数を使用して、「春・夏・秋・冬」とソートできるようにしたいです。上のプログラムはまだ途中なんですが、この場合比較関数はどのように実装すればうまくソートできるんでしょうか?分かる方、よろしくお願いいたします。

    • ベストアンサー
    • Perl

専門家に質問してみよう