0
2

More than 3 years have passed since last update.

リストのソート

Last updated at Posted at 2020-03-12

リストのソート

"文字+数字"形式のリストを数字でソートしたい。
ネットで検索しても全然見つからなかったので、うまいやり方ではないかもしれませんが、
書いてみました。
回路図の部品表や、IC(特にBGA)のPIN番号などがこういった形式になっています。
文字列はFPGAのPIN番号リストを抜粋しました。

1次元の場合

単純なソート

list1 = ["A1","A2","A3","A10","A11","A12","A13","A20","A21","A22","A23","A30","A31","A32"]
list1.sort()
print(list1)

結果:
桁がそろわない。

['A1', 'A10', 'A11', 'A12', 'A13', 'A20', 'A2', 'A21', 'A22', 'A23', 'A3', 'A30', 'A31', 'A32']

文字列の数字部分でソート

intでソートすれば番号順に並ぶので、いったん数値だけ取り出してソートした後、元のリストを取り出す。

import re

list1 = ["A1","A2","A3","A10","A11","A12","A13","A20","A21","A22","A23","A30","A31","A32"]

sort_list = [(re.search("[0-9]+", x).group(), x) for x in list1]    # ["数字", "元の文字列"]
sort_list.sort(key=lambda x:int(x[0]))                              # 数字をintでソート
print([x[1] for x in sort_list])                                    # 元の文字列だけ取り出す

結果:

['A1', 'A2', 'A3', 'A10', 'A11', 'A12', 'A13', 'A20', 'A21', 'A22', 'A23', 'A30', 'A31', 'A32']

もう少し複雑な場合

例えば、大規模なBGAの場合、A1~Yxxのあと、AA1から番号が続きます。

★★コメントに記載していただいた方法がシンプルです。考え方は以下になります。★★

# ここは見やすくするため書き方適当です。
list1 = 
["A1","A2","A3","A10","A11","A12","A20","A21","A22","AA1","AA2","AB1","AB2",
 "B1","B2","B3","B10","B11","B12","BB1","BB2","BB3","C1","C2"]
import re

# [ "文字", "数字", "元の文字列" ]
sort_list = [( re.search("[a-zA-Z]+", x).group(), re.search("[0-9]+", x).group(), x) for x in list1]
sort_list.sort(key=lambda x:(x[0],int(x[1])))                       # 文字 > 数字 の優先度でソート
print([x[2] for x in sort_list])                                    # 元の文字列だけ取り出す

結果:
文字でソートしただけでは、A,B,C,...,AA,AB,...の順にはならない。

['A1', 'A2', 'A3', 'A10', 'A11', 'A12', 'A20', 'A21', 'A22',
 'AA1', 'AA2', 'AB1', 'AB2',
 'B1', 'B2', 'B3', 'B10',
 'B11', 'B12', 'BB1', 'BB2', 'BB3', 'C1', 'C2']

文字数も考慮

import re

# [ "文字", "数字", "元の文字列" ]
sort_list = [( re.search("[a-zA-Z]+", x).group(), re.search("[0-9]+", x).group(), x) for x in list1]
sort_list.sort(key=lambda x:(len(x[0]),x[0],int(x[1])))        # 文字数 > 文字 > 数字 の優先度でソート
print([x[2] for x in sort_list])                                    # 元の文字列だけ取り出す

結果:

['A1', 'A2', 'A3', 'A10', 'A11', 'A12', 'A20', 'A21', 'A22',
 'B1', 'B2', 'B3', 'B10', 'B11', 'B12', 'C1', 'C2',
 'AA1', 'AA2', 'AB1', 'AB2', 'BB1', 'BB2', 'BB3']

2次元の場合

考え方は1次元と同じ。
3次元以上も同様にできるはず。

リスト例:

# ここは見やすくするため書き方適当です。
# [ "PIN番号", "機能名" ]
list2 = 
[['A1', 'GND'], ['A2', 'GND'], ['A10', 'IO_L2N_AD14N_94'], ['A11', 'IO_L2P_AD14P_94'],
 ['A20', 'IO_L1P_AD15P_91'], ['A21', 'IO_L22N_T3U_N7_DBC_AD0N_72'],
 ['AA1', 'GND'], ['AA2', 'GND'],
 ['AB1', 'MGTHRXN1_229'], ['AB2', 'MGTHRXP1_229'],
 ['B1', 'MGTHRXN1_234'], ['B2', 'MGTHRXP1_234'],
 ['BA1', 'GND'], ['BA2', 'GND'],
 ['BB1', 'GND'], ['BB2', 'GND'],
 ['C1', 'GND'], ['C2', 'GND'], 
 ['D1', 'MGTHRXN3_233'], ['D2', 'MGTHRXP3_233']]

単純なソート

list2.sort(key=lambda x:x[0])
print(list2)

結果:

[['A1', 'GND'], ['A10', 'IO_L2N_AD14N_94'], ['A11', 'IO_L2P_AD14P_94'],
 ['A2', 'GND'], ['A20', 'IO_L1P_AD15P_91'], ['A21', 'IO_L22N_T3U_N7_DBC_AD0N_72'],
 ['AA1', 'GND'], ['AA2', 'GND'], ['AB1', 'MGTHRXN1_229'], ['AB2', 'MGTHRXP1_229'],
 ['B1', 'MGTHRXN1_234'], ['B2', 'MGTHRXP1_234'],
 ['BA1', 'GND'], ['BA2', 'GND'], ['BB1', 'GND'], ['BB2', 'GND'],
 ['C1', 'GND'], ['C2', 'GND'], ['D1', 'MGTHRXN3_233'], ['D2', 'MGTHRXP3_233']]

文字数、文字、数値でソート

import re

list3 = []
for i in range(len(list2)):
    num = re.search("[0-9]+", list2[i][0]).group()                    # 数字だけ取り出す
    text = re.search("[a-zA-Z]+", list2[i][0]).group()                # 文字だけ取り出す
    list3.append([len(text), text, num, list2[i][0], list2[i][1]])    # ["文字数", "文字", "数字", "元の文字列"]

list3.sort(key=lambda x:(int(x[0]),x[1],int(x[2])))    # 文字数 > 文字 > 数字 の優先度でソート

# 元のリストを取り出す
sort_list = []
for i in range(len(list3)):
    sort_list.append([ list3[i][3], list3[i][4] ])
print(sort_list)

結果:

[['A1', 'GND'], ['A2', 'GND'], ['A10', 'IO_L2N_AD14N_94'], ['A11', 'IO_L2P_AD14P_94'],
 ['A20', 'IO_L1P_AD15P_91'], ['A21', 'IO_L22N_T3U_N7_DBC_AD0N_72'],
 ['B1', 'MGTHRXN1_234'], ['B2', 'MGTHRXP1_234'],
 ['C1', 'GND'], ['C2', 'GND'], ['D1', 'MGTHRXN3_233'], ['D2', 'MGTHRXP3_233'],
 ['AA1', 'GND'], ['AA2', 'GND'], ['AB1', 'MGTHRXN1_229'], ['AB2', 'MGTHRXP1_229'],
 ['BA1', 'GND'], ['BA2', 'GND'], ['BB1', 'GND'], ['BB2', 'GND']]
0
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2