質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

配列の要素の順位付けをしたい。

SmaSTATION
SmaSTATION

総合スコア16

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

2回答

1グッド

1クリップ

568閲覧

投稿2022/10/16 00:46

前提

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に対応付けしたい...

試したこと

ソートする方法とかはたくさんあると思うのですが、順位を反映させるというものが見つからず困ってます。

Cocode👏を押しています

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

lehshell

2022/10/16 01:20

SmaSTATION さん a=[12,43,7,15,9] とありますが、リスト内に同じ数字があった場合の期待する出力結果を記載しましょう。 2人の方はそれぞれ異なる受け取り方をされています。

回答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
melian

総合スコア16406

Cocode, ps_aux_grep👍を押しています
Cocode❤️を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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
PondVillege

総合スコア1066

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。