ホーム

OFF-SOFT.net

OFF-SOFT.net

ウェブやソフトウェアに関するサポート&情報サイトです。サイト構築からソフトウェアの作成、利用まであなたの助けになるかも・・・・しれません。たぶん・・。

Qt (B1) QListのソート

公開日| 2009年06月15日 | 1つのコメントがあります。
オブジェクトアドレスのQListのソート
以下のようにアドレスをQListで管理している場合、ソートはどうなるでしょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//	main
int main(int /* argc */, char* /*argv[]*/ )
{
	QList<MyName*> olist;
	MyName *my1=new MyName("test");
	MyName *my2=new MyName("taro");
	MyName *my3=new MyName("hanako");
	olist.append(my1);
	olist.append(my2);
	olist.append(my3);
 
	outputList("Not Sort",olist);
 
	//	sort - origin method
	qSort(olist);
	outputList("Sorted",olist);
 
	qDeleteAll(olist);
	olist.clear();
 
	return 0;
}

MyNameというクラスは、以前のサンプルと全く同じです。QListがアドレス管理になっただけです。

18行目は、QListでアドレス管理をする場合、自力でdeleteしなければなりません。それを実施してくれる関数が、qDeleteAllです。
自力でdeleteしても、数stepではありますが、知っておくと便利です。

これをコンパイルして実行してみると以下のような結果になります。

> debug\sort3.exe
Not Sort
[0]=test
[1]=taro
[2]=hanako
Sorted
[0]=test
[1]=taro
[2]=hanako

何も変化していません。オブジェクトのアドレスを比較しているに過ぎないので、当然な結果です。
求めているオブジェクトの内容の比較を行うには、その比較する関数を用意してあげなければなりません。

以下は、その例として、MyNameクラスに比較するstaticなメソッドを用意しました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//	class for test
class MyName
{
public :
 
	MyName(const QString name) { m_sname=name; };
	MyName(const MyName &other) { *this=other; };
 
	QString WhatYourName() const  { return m_sname; };
 
	MyName & operator =(const MyName &other) { m_sname=other.m_sname;return *this; };
	bool   operator<(const MyName &other) const { return (m_sname<other.WhatYourName()); };
 
	static bool   compare(const MyName *d1,const MyName *d2){ return (d1->WhatYourName()<d2->WhatYourName()); };
 
private:
	QString m_sname;
};

14行目が、そのstaticなメソッドです。
このメソッドの引数は、MyNameの比較対象となるアドレス2つです。その比較結果をboolで出力しています。

このあたりは、Cの標準関数qsortの扱い方と同じですね。

また、このメソッドを使って比較するようにqSortへパラメータを指定します。

1
	qSort(olist.begin(),olist.end(),MyName::compare);

この指定の仕方は、先の降順の指定と同じように指定します。最後の降順でした関数でなく、MyNameで用意したcompareを指定します。

これを、コンパイルして、実行してみましょう。

> debug\sort3_2.exe
Not Sort
[0]=test
[1]=taro
[2]=hanako
Sorted
[0]=hanako
[1]=taro
[2]=test

うまくソートできました。
ここでは、MyNameで、staticなメソッドを用意しましたが、同一の引数で、通常のCの関数を用意してあげても同じようにソートできます。

さて、最後にqUpperBound,qLowerBoundを少しやってみましょう。

QListの中で、位置を見つける
qUpperBound,qLowerBoundは、使い方によっては、非常に便利な関数ですので、簡単に説明してみます。
qUpperBound,qLowerBoundは、それぞれ、ソートされたQListの中で、指定された情報の最後、最初のiteratorを出力してくれるものです。

簡単な例で説明します。以下のような名前を持つQList<MyName>があるとしましょう。
そこで、"test"という名前を持つ全てのアイテムを取り出したいときなどに、qUpperBound,qLowerBoundは、威力を発揮します。

QList[0]=hanako
QList[1]=taro
QList[2]=test
QList[3]=test
QList[4]=test
QList[5]=test1

1
2
3
4
	MyName my_check("test");
 
	QList<MyName>::iterator ipos1=qUpperBound(olist.begin(),olist.end(),my_check);
	QList<MyName>::iterator ipos2=qLowerBound(olist.begin(),olist.end(),my_check);

このように、qUpperBound,qLowerBoundを使用します。my_checkは、比較のためのオブジェクトです。
ipos1には、QList[5]=test1
ipos2には、QList[2]=test
が設定されます。

つまり、qLowerBoundは、"test"という名前をもつ先頭のオブジェクトQList[2]を捕らえます。
また、qUpperBoundは、"test"という名前をもつ最後尾+1のオブジェクトQList[5]を捕らえます。
最後尾は、QList[4]ですが、+1の位置を取り出すことに注意します。

以下は、ソートの有無で、どのように検索されるかをテストしたものです。
当然、昇順にソートされていない場合の動作は、保障されません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//	main
int main(int /* argc */, char* /*argv[]*/ )
{
	QList<MyName>::iterator ipos;
	QList<MyName> olist;
	MyName my1("test",1);
	MyName my12("test",2);
	MyName my13("test",3);
	MyName my2("taro",4);
	MyName my3("hanako",5);
	MyName my14("test1",6);
	olist.append(my1);
	olist.append(my12);
	olist.append(my13);
	olist.append(my2);
	olist.append(my3);
	olist.append(my14);
 
 
	MyName my_check("test",-1);
 
	outputList("Not Sort",olist);
 
	ipos=qUpperBound(olist.begin(),olist.end(),my_check);
	outputItem("[Not Sort(Upper)]",ipos,olist.end());
 
	ipos=qLowerBound(olist.begin(),olist.end(),my_check);
	outputItem("[Not Sort(Lower)]",ipos,olist.end());
 
	//	sort - qLess
	qSort(olist.begin(),olist.end(),qLess<MyName>());
	outputList("Sorted(qLess)",olist);
 
	ipos=qUpperBound(olist.begin(),olist.end(),my_check);
	outputItem("[Sorted(qLess)(Upper)]",ipos,olist.end());
 
	ipos=qLowerBound(olist.begin(),olist.end(),my_check);
	outputItem("[Sorted(qLess)(Lower)]",ipos,olist.end());
 
	//	sort - qGreater
	qSort(olist.begin(),olist.end(),qGreater<MyName>());
 
	outputList("Sorted(qGreater)",olist);
 
	ipos=qUpperBound(olist.begin(),olist.end(),my_check);
	outputItem("[Sorted(qGreater)(Upper)]",ipos,olist.end());
 
	ipos=qLowerBound(olist.begin(),olist.end(),my_check);
	outputItem("[Sorted(qGreater)(Lower)]",ipos,olist.end());
 
	return 0;
}

上記をコンパイルして、実行した結果は、以下のとおりです。

> debug\sort5.exe
Not Sort
[0]=test(1)
[1]=test(2)
[2]=test(3)
[3]=taro(4)
[4]=hanako(5)
[5]=test1(6)
[Not Sort(Upper)]test1(6)
[Not Sort(Lower)]test1(6)
Sorted(qLess)
[0]=hanako(5)
[1]=taro(4)
[2]=test(1)
[3]=test(3)
[4]=test(2)
[5]=test1(6)
[Sorted(qLess)(Upper)]test1(6)
[Sorted(qLess)(Lower)]test(1)
Sorted(qGreater)
[0]=test1(6)
[1]=test(2)
[2]=test(3)
[3]=test(1)
[4]=taro(4)
[5]=hanako(5)
[Sorted(qGreater)(Upper)]** last ** previous item --> hanako(5)
[Sorted(qGreater)(Lower)]test1(6)

今回は、基本的なソート処理を行いました。 QtAlgorithmsでは、その他にも検索するqFindや、コピーするqCopyなど便利なものがあります。
QtAlgorithmsは、基本的にiteratorで管理しているテンプレートクラスであれば動作します。
(QVectorから、QListへのコピーなどもできます。)

自分で作成することもできますが、知っておくと便利です。

何かお気づきの点があれば、コメントいただければ幸いです。

もっと、Qt関連について詳しく知りたい方は、以下の本なども良いと思います。
Qtに関する日本語の本が少ないですね。「入門書」は、さすがに、このページを読まれるくらいの方は不要だと思います。
やっぱり、本+ネット+試してみる!!の3本柱でやっていく以外にないように思います。


コメント

1つのコメントがあります。 “Qt (B1) QListのソート”


  1. oscar
    2014年02月03日 @ 11:26:06

    buena informacion
    me ayudo en mucho

コメントをどうぞ







  • はてなブックマークへ追加する
  • Facebookでシェアする
  • twitter でつぶやく
  • Google Plusでシェアする
  • Pocketでシェアする
ページトップへ