Qt   言語   コレクション

ホーム   C/C++チュートリアル  
目次

コレクション

コレクションは、複数のデータを格納できる型の総称です。コンテナと、呼ばれることもあります。

コンテナは GUI フレームワークでは、レイアウト用のウィジェットの総称なので、 ここではコレクションと呼ぶことにします。

Qt には、QList、QVector、QLinkedList、QMap、QHash のコレクションがあります。

コレクションは各値を順番で管理するシーケンシャル(連続)コレクションと、各値に名前をつけて、 その名前で管理するアソシエティブ(連想)コレクションがあります。

QList と QVector と QLinkedList はシーケンシャル(連続)コレクションで、QMap と QHash はアソシエティブ(連想)コレクションになります。

シーケンシャルコレクションは配列と呼ばれることが多く、アソシエティブコレクションは辞書もしくは連想配列と呼ばれることが多いです。

QVector

QVector は各要素 (それぞれの値) を隣接するメモリに格納していきます。各要素のインデックス (番号) で高速にアクセスできます。

大きな QVector になると、挿入操作が遅くなるので、その場合は QList を使ったほうが良いでしょう。

この章では、collection ディクトリに collection.cpp を作成して、作業を進めていきます。

collection.cpp


#include <QVector>
#include <QTextStream>

int main (void)
{
  QTextStream out (stdout);
  
  QVector<int> vals = {1, 2, 3, 4, 5};
  
  out << QString("ベクターのサイズは: ") << vals.size() << Qt::endl;
  out << QString("最初の要素は: ") << vals.first() << Qt::endl;
  out << QString("最後の要素は: ") << vals.last() << Qt::endl;
  
  vals.append(6);
  vals.prepend(0);
  
  out << "各要素は: ";
  
  for (int val: vals)
    out << val << " ";
  
  out << Qt::endl;
  return 0;
}


コード説明

  1. #include <QVector>
    QVector クラスです。
  2. #include <QTextStream>
    Qt でテキストの入出力を担当しているクラスです。
  3. #include <QString>
    Qt で文字列を担当しているクラスです。
  4. QTextStream out (stdout);
    テキストストリームが out という名前で標準出力 (ターミナル) を使うと宣言しています。
    out という名前の部分は任意の名前に変えられます。 なぜ iostream ではいけないのかというと、iostream では QStのいろいろなメソッドが使えないからです。
  5. QVector vals = {1, 2, 3, 4, 5};
    QQVectro のシーケンシャルを宣言して初期化しています。何型にするかは < と > で囲みます。

ビルド

collection ディレクトリで作業を続けます。


// プロジェクトを作ります。
qmake -project

// Windows の場合は出来上がった datetime.pro の末尾に次の一行を追加します。
CONFIG += console

// Makefile を作ります。
qmake

// 実行ファイルを作ります。
// Mac Linux の場合は make します。
make

// Windows の場合は nmake します。make じゃなく nmake です。
nmake

// エラーが表示されたら、collection.cpp を見直して、make あるいは nmake する作業を繰り返します。

実行


// Mac の場合は datetime ディレクトリに collection.app ができあがります。
// GUI アプリケーションならこれをダブルクリックすると起動できますが、
// 今回はコマンドラインアプリなので次のようにして実行します

./collection.app/Contents/MacOS/collection

// 結果
ベクターのサイズは: 5
最初の要素は: 1
最後の要素は: 5
各要素は: 0 1 2 3 4 5 6 

// Linux の場合には collection ディレクトリに collection という実行ファイルが出来上がっていますのでそれをそのまま実行します
./collection

// 結果 は同じ

// Windows の場合には collection ディレクトリの中の release ディレクトリに collection.exe が出来上がっています。
// release ディレクトリに移動して、collection.exe を実行します。
collection

// 結果 は同じ

QList

QList もシーケンシャルコレクションですが、各要素への高速な挿入と削除ができます。

Qt で最もよく使われるコレクションです。

collection.cpp


#include <QTextStream>
#include <QList>

int main (void)
{
  QTextStream out (stdout);
  
  QList writers = {QString("むらかみはるき"),
                            QString("なつめそうせき"),
                            QString("あくたがわりゅうのすけ"),
                            QString("かわばたやすなり"),
                           };
  
  for (int i=0; i < writers.size(); i++)
    out << writers.at(i) << Qt::endl;
  
  writers << QString("いけなみしょうたろう") << QString("あかがわじろう");
  out << "***********************" << Qt::endl;
  std::sort(writers.begin(), writers.end());
  out << QString("ソートされました。") << Qt::endl;
  
  for (QString writer : writers)
    out << writer << Qt::endl;
  
  return 0;
}

漢字だとソートされているのかどうか分かりにくいのでひらがなにしました。

結果


なつめそうせき
あくたがわりゅうのすけ
かわばたやすなり
***********************
ソートされました。
あかがわじろう
あくたがわりゅうのすけ
いけなみしょうたろう
かわばたやすなり
なつめそうせき
むらかみはるき

コード説明

  1. writers << "いけなみしょうたろう" << "あかがわじろう";
    << 演算子でもコレクションの末尾に要素を追加できます。
  2. std::sort(writers.begin(), writers.end());
    std::sort メソッドで昇順ソートができます。

QStringList

QStringList は QString 専用のシーケンシャルコレクションで、高速な挿入と削除ができます。

collection.cpp

#include <QTextStream>
#include <QList>


int main (void)
{
  QTextStream out (stdout);
  
  QString string = "硬貨, 本, コップ, 鉛筆, 時計, しおり";
  QStringList items = string.split(",");
  QStringListIterator it(items);
  
  while (it.hasNext())
    out << it.next().trimmed() << Qt::endl;
  
  return 0;
}
 

結果


硬貨
本
コップ
鉛筆
時計
しおり
 

コード説明

  1. QStringList items = string.split(",");
    split メソッドは文字列を引数の , (カンマ)で分割し、分割した部分文字列を要素とする新しリストを作ります。
  2. QStringListIterator it(items);
    これd、it の中に、itemsリストの情報が入ります。

  3. while (it.hasNext())
    it に次の要素がある限りループされます。
  4. out << it.next().trimmed() << endl;
    it は最初、先頭の配列の先頭の要素の前にありますから、まず先頭の要素が出力されて、it は次の要素の前に移動します。 timmed() メソッドは要素の文字列の前後にある空白文字を削除します。文字列の中にある空白文字は削除しません。

比較演算子は QTime、QDateTime にも使えます。

QSet

QSet は値の集合ですが、各要素には順序はなく、また同じ値の要素を持つこともできません。

collection.cpp


#include <QTextStream>
#include <QList>
#include <QSet>

int main (void)
{
  QTextStream out (stdout);
  
  QSet<QString> cols1 = {"イエロー", "レッド", "ブルー"};
  QSet<QString> cols2 = {"ブルー", "ピンク", "オレンジ"};
  
  out << QString("セットに要素は") << cols1.size() << QString("個あります。") << Qt::endl;
  cols1.insert("ブラウン");
  out << QString("セットに要素は") << cols1.size() << QString("個あります。") << Qt::endl;
  cols1.unite(cols2);
  out << QString("セットに要素は") << cols1.size() << QString("個あります。") << Qt::endl;
  for (QString val : cols1)
    out << val << Qt::endl;
  
  QList list = cols1.values();
  std::sort(list.begin(), list.end());
  
  out << "**********************************" << Qt::endl;
  out << QString("ソートしました。") << Qt::endl;
  out << "**********************************" << Qt::endl;
  
  for (QString val : list)
    out << val << Qt::endl;
  
  return 0;
}

結果


セットに要素は3個あります。
セットに要素は4個あります。
セットに要素は6個あります。
オレンジ
レッド
ピンク
イエロー
ブラウン
ブルー
**********************************
ソートしました。
**********************************
イエロー
オレンジ
ピンク
ブラウン
ブルー
レッド

起動するたびに最初の文字の並びは変わります。QSet には順序がないからです。

コード説明

  1. cols1.insert("ブラウン");
    QSet には順序がないので先頭でもなく、最後でもなく、単に挿入して要素を増やしています。
  2. cols1.unite(cols2);
    2つの QSet を結合しています。要素は合わせて7個になるはずですが、同じ値の要素は持てないので、2つあるブルーは1つになって、合計6個になります。
  3. QList list = cols1.values();
    std::sort(list.begin(), list.end());
    QSet には順序の概念がないので、ソートしても意味がありません。そこでまず QList に代入してからソートしています。

QMap

QMap は、キーと値のペアを格納するアソシエティブコレクションです。連想配列や辞書とも呼ばれます。

QMap の各要素にはキーを使って素早くアクセスできます。

collection.cpp


#include <QTextStream>
#include <QMap>

int main (void)
{
  QTextStream out (stdout);
  
  QMap<QString, int> m = {{"鉛筆", 6}, {"りんご", 3}};
  m.insert("空き缶", 4);
  
  QList<int> vals = m.values();
  out << QString("値は:") << Qt::endl;
  for (int val : vals)
    out << val << Qt::endl;
  out << "*********************" << Qt::endl;
  
  QList<QString> keys = m.keys();
  out << QString("キーは:") << Qt::endl;
  for (QString key : keys)
    out << key << Qt::endl;
  out << "*********************" << Qt::endl;
  
  QMapIterator it(m);
  out << QString("ペアは:") << Qt::endl;
  while (it.hasNext())
  {
    it.next();
    out << it.key() << ": " << it.value() << Qt::endl;
  }
  
  return 0;
}

結果


値は:
3
4
6
*********************
キーは:
りんご
空き缶
鉛筆
*********************
ペアは:
りんご: 3
空き缶: 4
鉛筆: 6

コード説明

  1. QMap m = {{"鉛筆", 6}, {"りんご", 3}};
    値の型としてQString と int を宣言しています。QString がキーになり、int が値になります。
  2. QList vals = m.values();
    QMap の values メソッドで値だけのリストが取り出せます。
  3. QList keys = m.keys();
    QMap の keys メソッドでキーだのリストが取り出せます。
  4. QMapIterator it(m);
    QMap のイテレータ it を宣言しています。it の中に QMap の情報が入ります。
  5. while (it.hasNext())
    イテレータの後ろに値がある場合 true になります。
  6. it.next();
    最初イテレータはマップの先頭にいて、どの要素にもアクセスしていません。
    it.next() ではじめて最初の要素にアクセスすることになります。


45 visits
Posted: Apr. 02, 2025
Update: Apr. 02, 2025

ホーム   C/C++チュートリアル   目次