Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8899

【C#,Unity】Dictionaryをfloat基準で昇順にSortしようとしたら謎処理を挟んでいた話

$
0
0

追記【2019/11/15】

@albireo様にアドバイスしていただいたSortedListの方が簡易的かつ無駄なく処理できたので
記事の末尾に追加しておきました。

この記事の狙い

自分の経験を書き記すとともに、有識者の方々からアドバイスや説明をもらえたらいいなぁ。
という期待。

あらすじ

Unityで画面内に映っているTargetを取得&自キャラとTargetの距離を取得できるようになったので、
これを「距離が近い順」で並べ替えたい!と思い、色々調べながら試してみることに。

本題

まず「画面内に映っているTarget」と「Targetまでの距離」、この二つの情報を紐付けるには
どうすればいいのかを調べるところから始めた。

これは調べると直ぐに出てきた、最初はList<>か配列[ ]でなんとかするしかないのかな?とか考えていたが、
調べてみるとDictionaryという超便利なクラスがあるではないか。
早速、意気揚々と使ってみる。

Dictionary<GameObject,float>ProvisionalValue=newDictionary<GameObject,float>();ProvisionalValue.Add(hit,target_distance);

よし、これで情報の紐付けはできたな...!
後はこれを「距離が近い順」で並べ替えるだけだ...!

なんだ楽勝じゃん。勝ったな、風呂入ってくる。

ここからが本当の地獄だ...!

さて、ちゃちゃっとSortして終わらせるか~

ProvisionalValue.Sort();

...あれ、できない。なになに?DictionaryにはSortの定義が含まれていない?
あら、そうなのか...。じゃあどうやって並び替えするんだろう、調べてみるか...。

【C#入門】DictionaryのKey、Valueの使い方(要素の追加、取得も解説)

ははーん、Linqを使えば出来るのね。試したことが無いけど、やってみるか...。

ここで訳の分からないことをし始める(多分色々調べているうちにいろんな記事の情報が入り混じった)

えーっと、まずはソートする基準がいるから(?)floatだけをList<>で取得してからこれをOrderByで
並べ替えて...、あれ?Valueが定義が含まれていない...?(Listだから)

これは何かがおかしい...!という感じで混迷を極めた結果、こうなった。

privatestaticDictionary<GameObject,float>hitsOB=newDictionary<GameObject,float>();privatestaticDictionary<GameObject,float>ProvisionalValue=newDictionary<GameObject,float>();{ProvisionalValue.Add(hit,target_distance);Sort(ProvisionalValue);}publicstaticvoidSort(Dictionary<GameObject,float>itemTable)//取得したオブジェクトと距離のデータを距離が近い順でソートするメソッド{IOrderedEnumerable<KeyValuePair<GameObject,float>>_table_1=itemTable.OrderBy(selector=>selector.Value);foreach(KeyValuePair<GameObject,float>pairin_table_1){hitsOB.Add(pair.Key,pair.Value);}}

改めて見ると何やってるんだか、と思いました。

ProvisionalValueに格納したデータをOrderByで並べ替えて、並べ替えたデータを_table_1に格納して、
foreachでpairに一つずつ格納してhitsOBに順に格納....

いや、これ普通にProvisionalValueをOrderByでソートすればいいじゃん。

はい、というわけでそうした結果がこちら。

ProvisionalValue.Add(hit,target_distance);ProvisionalValue.OrderBy(x=>x.Value);

二行で終了。(なぜ俺はあんなムダな時間を...)

ふりかえり

そもそも混乱した理由は「よく理解していなかったから」につきます。
Dictionaryの値の取得方法すら理解していなかったが為に、KeyとValueがなんなのか分からずに使っていた
結果、今回のような無駄な時間を浪費する羽目になりました...。

まさしく「知識は身を助ける」を身をもって実感しました。

追加記事【SortedList】

先に紹介したDictionaryクラスは値を格納した後にOrderByでソートしていましたが、
SortedListクラスを使用すればわざわざソートする必要がなくなります。

しかし、注意しなければいけない点があります。
それはSortedList <TKey,TValue>では、キー(TKey)の値を基準にソートされます。

今回の例で行くと、先の紹介したDictionaryはDictionary<GameObject,float>としていましたが、
これだとTKeyの値に代入しているGameObjectのソート基準はNameの頭文字をABCD...順で並び替える為、
ソートの基準は距離で並び替えたかったので、順番を入れ替える必要がありました。

ということを踏まえた上で変更したものが以下の流れです。(距離の所得等は省いています)

privateSortedList<float,GameObject>ProvisionalValue;voidStart(){ProvisionalValue=newSortedList<float,GameObject>();}publicvoidSort(){ProvisionalValue.Add(target_distance,hit);foreach(variteminProvisionalValue){Debug.Log("Distance : "+item.Key+" / Object : "+item.Value);}}

これでコンソールに距離順で距離とオブジェクト名が表示されます。


Viewing all articles
Browse latest Browse all 8899

Trending Articles