本日は、かなり具体的なのですがプロパティリストに登録した色々な数字を元に「ソート」をする方法です。 実装はできたのですが、凄く強引な方法で、恐らくもっと正しい方法があるのではないかと思います。 ぜひ、良い方法があれば教えて欲しいです。
実装
まずは今回やりたい事は以下になります。
プロパティリストにあるデータの一つに対して昇順で並べたい。
準備 - プロパティリスト(plist)を準備する
まずはソートする元のデータをプロパティリストで作成します。
具体的に私はお店に並ぶアイテムを作成したいので、「アイテム番号」「値段」などを個別に設定をしていきます。
考え方
まずは、どのように実装をするかの「考え方」です。 方法は恐らく星の数ほどありますが、何をやりたいかを決めておきます。
- プロパティリストからデータを取り出す
- 取り出したデータをソートする
- ソートしたデータとプロパティリストを照合して、新しい配列を作る
このような感じで作成します。
実装
それでは順番に実装をします。 今回は、プロパティリストに登録されているアイテムの「値段」でソートをします。
プロパティリストからデータを取り出す
[c]
CCDictionary *itemList = CCDictionary::createWithContentsOfFile("items.plist");
for (int i = 0; i < 50; i++) {
CCString nameString = CCString::createWithFormat("item%i",i); CCDictionary itemList2= (CCDictionary)itemList->objectForKey(nameString->m_sString.c_str()); CCString moneyString = (CCString*)itemList2->objectForKey("money"); makeNum =moneyString->intValue();
//プロパティリストの順番を配列に格納します。 CCString *string = CCString::createWithFormat("%i",i); array->addObject(string);
//取り出した値を配列(CCArray)に格納していきます。 CCString *makeString2 = CCString::createWithFormat("%i",makeNum); array2->addObject(makeString2);
}
[/c]
「ソートをする値」と「後で照合する時に必要な元データの順番」をそれぞれ配列に格納します。
取り出したデータをソートする
先ほど取り出した配列を使って、値をソートします。 その場合、C++にあるqsort()を利用します。
[c]
int base[array->count()];
//baseにプロパティリストで取り出した値を入れていきます。 for (int j = 0; j < array2->count(); j++) {
CCString string = (CCString)array2->objectAtIndex(j); int itemNum = (int)string->intValue();
base[j] = itemNum;
}
//ソート(昇順) qsort(base, array->count(), sizeof(int), comp);
[/c]
CCArrayでは、ソートできない(恐らく)ので、intで配列を作りなおしてqsort()を利用します。
ソートしたデータとプロパティリストを照合して、新しい配列を作る
最後に、ソートした配列の順番を元に、プロパティリストの配列を変更していきます。
[c]
for (int j = 0; j < array->count(); j++) {
int sortNum = base[j];
for (int k = 0; k < array->count(); k++) {
bool copyNume = false;
CCString *panst = (CCString*)array2->objectAtIndex(k);
int panNum = (int)panst->intValue();
//ソートした値と、プロパティリストの値が一致した場合
if (panNum == sortNum) {
//プロパティリストからアイテム番号を取り出す。
CCString *itemNumString = (CCString*)array->objectAtIndex(k);
int itemNum = (int)itemNumString->intValue();
CCString *retirmString = CCString::createWithFormat("%i",itemNum);
//ここでは、配列の重複を失くすために、一度取り出したアイテム番号を除外しています。
int arrayCount = array3->count();
if (arrayCount > 0) {
for (int k = 0; k < array3->count(); k++) {
CCString *removeNumString = (CCString*)array3->objectAtIndex(k);
int removeNum = (int)removeNumString->intValue();
if(itemNum == removeNum){
isRemove = true;
}
}
}
//重複でない場合に配列に格納
if (isRemove) {
}else{
//重複除外用の配列に格納 array3->addObject(retirmString);
//ソートされた配列に格納 newArray->addObject(retirmString);
break;
}
}
}
}
[/c]
上記コードのnewArrayがソートされたアイテムの配列になります。 これで何とか上手く動作しているのですが、もっと簡単でシンプルは方法があると思います。
最後に
同じ数字がある場合に、どうすればその数字を除外するかでかなり迷いました。 これだけで3日くらい時間を使いました。プログラミング能力が全然足りないと感じる日々です。
CCArrayクラスにはソートする機能がないので、int[]で利用するqsort()を使っている所がソートの鍵でした。 冒頭にも書きましたが、おそらくもっと良い方法があると思います。 もし、良い方法があれば教えて欲しいです。
C++ ポケットリファレンス 高橋 晶,安藤 敏彦,一戸 優介,楠田 真矢,道化師,湯朝 剛介 技術評論社 売り上げランキング : 36496 Amazonで詳しく見る |