リストのソート

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

## 1次元の場合
### 単純なソート

```python
list1 = ["A1","A2","A3","A10","A11","A12","A13","A20","A21","A22","A23","A30","A31","A32"]
list1.sort()
print(list1)
```
結果：
桁がそろわない。

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

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

```python
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])                                    # 元の文字列だけ取り出す
```
結果：

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

### もう少し複雑な場合
例えば、大規模なBGAの場合、A1～Yxxのあと、AA1から番号が続きます。

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

```python
# ここは見やすくするため書き方適当です。
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"]
```


```python
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,...の順にはならない。

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

### 文字数も考慮

```python
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])                                    # 元の文字列だけ取り出す
```
結果：

```python
['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次元以上も同様にできるはず。

リスト例：

```python
# ここは見やすくするため書き方適当です。
# [ "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']]
```

### 単純なソート

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

結果：

```python
[['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']]
```

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

```python
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)
```

結果：

```python
[['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']]
```