前提
a=[12,43,7,15,9] の配列の要素を小さい順に並べたときのように順位で表示したいです。
a=[12,43,7,15,9]であれば、
出力結果は(2,4,0,3,1)です。
実現したいこと
個人的にはaの配列をソートして、新しい配列を作り、その配列の順番をaの配列に反映させるプログラムを作ってみたいと思っています。
下記のプログラムはソートしたとこで終わっています。
ここからどうすればいいでしょうか。
該当のソースコード
Python
1a=[12,43,7,15,9] 2 3new_list=sorted(a) 4 5//aの配列をソートした新しい配列の要素番号をaに対応付けしたい...
試したこと
ソートする方法とかはたくさんあると思うのですが、順位を反映させるというものが見つからず困ってます。
以下のような質問にはグッドを送りましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 間違っている
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
2022/10/16 01:20
回答2件
3
リスト内に重複する要素がない場合。
python
1>>> a = [12, 43, 7, 15, 9] 2>>> [sorted(a).index(x) for x in a] 3[2, 4, 0, 3, 1]
投稿2022/10/16 01:03
編集2022/10/16 01:06総合スコア16406
良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
0
ベストアンサー
個人的にはaの配列をソートして、新しい配列を作り、その配列の順番をaの配列に反映させるプログラムを作ってみたいと思っています。
これを実現すると以下になります.
Python
1a = [12, 43, 7, 15, 9] 2new_list = sorted(a) # aの配列をソートして、新しい配列を作り 3 4rank = [0] * len(a) 5for i in range(len(new_list)): # その配列の順番を 6 for j in range(len(a)): # aの配列に 7 if new_list[i] == a[j]: 8 rank[j] = i # 反映させる 9 10print(rank) # [2, 4, 0, 3, 1]
配列の要素とその順番が一致しているかどうか判定するのに2重のループになっているため,要素数N
に対して時間計算量O(N^2)
のアルゴリズムとなっており,非常に低速な実装です.また,要素に重複がある場合正しく動作しないので,もっとコードを書く必要があります.
この問題を解決すべく,ソートする際に,元の配列のインデックス情報の方を並び替えてしまえば良い,という発想が必要になります.ここではソートにかかる時間計算量そのままO(N log N)
で済みます.
これは一般に,argsort()
と呼ばれる動作になり,順位を求める実装と合わせて次のようになります.
Python
1def argsort(arr, reverse = False): # ソート前のindexを返す 2 return sorted(range(len(arr)), key = arr.__getitem__, reverse = reverse) 3 4a = [12, 43, 7, 15, 9] 5rank = [0] * len(a) 6for r, idx in enumerate(argsort(a)): # r: 順位, idx: argsortで求めたソート前のindex 7 rank[idx] = r # ソート前のindexであるidxを使ってrank配列のidx番目の順位をrにする 8print(rank) # [2, 4, 0, 3, 1]
また,argsort()
の実装方法はこれに限りません.あくまで一例です.他にも
Python
1def argsort(arr, reverse = False): 2 return [x for x, y in sorted(enumerate(arr), key = lambda x: x[1], reverse = reverse)]
などがあります.なお基本構造はどれも同じで,ソートの対象key
の指定を,key = arr.__getitem__
として値を指定するか,enumerate()
で列挙される要素の1番目に対象の値があることを利用したkey = lambda x: x[1]
とするなど,複数のテクニックが存在します.ソートの対象はリストの値,実際に並び替えられたのはリストのインデックス.といった具合です.
stack overflow - How to get indices of a sorted array in Python
今回はこれを使ってindexを保持したソートをすることで,O(N log N)
の時間計算量で順位を反映させることができました.
このままだと同じ値でも別々の順位を割り振られる実装になっていますので,次のように変更することもできます.
Python
1rank = [0] * len(a) 2rank_no = set() 3for idx in argsort(a): 4 rank_no.add(a[idx]) 5 rank[idx] = len(rank_no)
余談ですが「たまたま」例示いただいたデータ[12, 43, 7, 15, 9]
においてargsort()
の結果と求めた順位rank
が同じになっています(非常にややこしいです).argsort()
の結果を例示しなかったのは混乱するからです...
結論
Python
1import random 2 3def argsort(arr, reverse = False): 4 return sorted(range(len(arr)), key = arr.__getitem__, reverse = reverse) 5 6def calc_rank1(arr, reverse = False): # 重複があっても左から順に順位付け 7 rank = [0] * len(arr) 8 for r, idx in enumerate(argsort(arr, reverse)): 9 rank[idx] = r 10 return rank 11 12def calc_rank2(arr, reverse = False): # 重複は同じ順位 13 rank = [0] * len(arr) 14 rank_no = set() 15 for idx in argsort(arr, reverse): 16 rank_no.add(arr[idx]) 17 rank[idx] = len(rank_no) - 1 18 return rank 19 20a = [random.randint(0, 20) for _ in range(10)] 21 22print("original:", a) # [9, 6, 9, 19, 9, 9, 15, 3, 10, 12] 23print("argsort :", argsort(a)) # [7, 1, 0, 2, 4, 5, 8, 9, 6, 3] 24print("rank1 :", calc_rank1(a)) # [2, 1, 3, 9, 4, 5, 8, 0, 6, 7] 25print("rank2 :", calc_rank2(a)) # [2, 1, 2, 6, 2, 2, 5, 0, 3, 4]
投稿2022/10/16 01:05
編集2022/10/16 05:46総合スコア1066
良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
関連した質問
Q&A
解決済
JavaScript forとsetTimeoutと配列を組み合わせた謎の挙動について
回答2
クリップ0
更新
2023/01/24
Q&A
解決済
2つの三次元ベクトルから角度を求める問題。
回答2
クリップ0
更新
2023/02/06
Q&A
解決済
最速で配列からデータを取り出し、正規表現で検索したい。
回答3
クリップ1
更新
2023/01/31
Q&A
解決済
配列の要素の順位付けをしたい。
回答2
クリップ1
更新
2022/10/16
Q&A
受付中
2つのベクトルから角度を求めるプログラム
回答2
クリップ0
更新
2023/02/06
Q&A
解決済
5回、自然数を入力し、その中で最小値と最大値を除いた合計値を出力するプログラム
回答4
クリップ0
更新
2023/02/07
Q&A
解決済
while構文を使う際のbreakの位置と使い方
回答1
クリップ0
更新
2023/02/04
Q&A
解決済
Raspberry Pi Picoの内蔵温度センサーから温度を取得したい
回答1
クリップ0
更新
2023/02/04
同じタグがついた質問を見る
Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。