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

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

ただいまの
回答率

90.98%

  • Python 3.x

    4134questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

python3: 文字と数字を含む文字列の数字でsortする方法

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 376

kujiraryo

score 1

前提・実現したいこと

python3で、[A1,A2,....,A100,B1,B2...,,B100]のようなリストの数字部分でsortがしたい。つまり [A1,B2,A2,B2,...A100,B100] というリストがほしい

発生している問題・エラーメッセージ

最初に文字と数字に分割し、数字をint型に変換しsortするというやり方をやったのですが、もっと効率のいいやり方はないでしょうか?

(また文字と数字の分割もsplitするために間に"/"を入れましたが、これももっと良い方法があれば教えてください)

ソースコード

#テスト用の文字列作成
A = ["A" + str(n) for n in range(1,101)]
B = ["B" + str(n) for n in range(1,101)]
AB = A + B 
import random
random.shuffle(AB) # ついでにシャッフル

#シーケンスを文字と数字で分割するために文字と数字の間に "/" を挿入する
AB_list = []
for ab in AB:
    for n in range(len(ab)-1):
        if ab[n].isalpha() and ab[n+1].isdigit():
            AB_list += [ab.replace(ab[n]+ab[n+1] , ab[n]+"/"+ab[n+1])]        

#"/"でsplitするついでに数字をintに変換する
ab_list = []
for x in AB_list:
    ab_list.append([int(y) if y.isdigit() else y for y in x.split("/")]) 

#ab_lintの二列目(intタイプの数字)でsort、次に文字でsortする
hoge = sorted(ab_list,key=lambda n:(n[1],n[0]))

#一列目(str)と二列目(int)をjoinで連結
ab = ["".join(map(str,x)) for x in hoge]

試したこと

課題に対してアプローチしたことを記載してください

補足情報(言語/FW/ツール等のバージョンなど)

使っているのはpython 3.6.2です

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

正規表現を使い、対象の文字列の長さに関わらず数字部分の大小でソートするようにしてみました。

import random
import re
A = ["BA" + str(n) for n in range(1,101)]
B = ["B" + str(n) for n in range(1,101)]
AB = A + B
random.shuffle(AB)

print(sorted(AB, key=lambda x:int((re.search(r"[0-9]+", x)).group(0))))

実行結果

$ python test.py
['B1', 'BA1', 'BA2', 'B2', 'BA3', 'B3', 'BA4', 'B4', 'BA5', 'B5', 'B6', 'BA6', 'BA7', 'B7', 'BA8', 'B8', 'B9', 'BA9', 'BA10', 'B10', 'B11', 'BA11', 'B12', 'BA12', 'BA13', 'B13', 'BA14', 'B14', 'B15', 'BA15', 'B16', 'BA16', 'BA17', 'B17', 'BA18', 'B18', 'B19', 'BA19', 'B20', 'BA20', 'B21', 'BA21', 'BA22', 'B22', 'BA23', 'B23', 'B24', 'BA24', 'B25', 'BA25', 'B26', 'BA26', 'BA27', 'B27', 'BA28', 'B28', 'BA29', 'B29', 'BA30', 'B30', 'B31', 'BA31', 'BA32', 'B32', 'BA33', 'B33', 'B34', 'BA34', 'BA35', 'B35', 'BA36', 'B36', 'B37', 'BA37', 'BA38', 'B38', 'BA39', 'B39', 'B40', 'BA40', 'BA41', 'B41', 'BA42', 'B42', 'B43', 'BA43', 'BA44', 'B44', 'B45', 'BA45', 'B46', 'BA46', 'B47', 'BA47', 'B48', 'BA48', 'B49', 'BA49', 'BA50', 'B50', 'B51', 'BA51', 'B52', 'BA52', 'BA53', 'B53', 'BA54', 'B54', 'BA55', 'B55', 'B56', 'BA56', 'BA57', 'B57', 'BA58', 'B58', 'B59', 'BA59', 'B60', 'BA60', 'BA61', 'B61', 'B62', 'BA62', 'B63', 'BA63', 'B64', 'BA64', 'B65', 'BA65', 'B66', 'BA66', 'BA67', 'B67', 'BA68', 'B68', 'B69', 'BA69', 'BA70', 'B70', 'B71', 'BA71', 'BA72', 'B72', 'B73', 'BA73', 'BA74', 'B74', 'BA75', 'B75', 'B76', 'BA76', 'B77', 'BA77', 'BA78', 'B78', 'B79', 'BA79', 'B80', 'BA80', 'B81', 'BA81', 'B82', 'BA82', 'BA83', 'B83', 'BA84', 'B84', 'B85', 'BA85', 'B86', 'BA86', 'BA87', 'B87', 'B88', 'BA88', 'B89', 'BA89', 'B90', 'BA90', 'BA91', 'B91', 'B92', 'BA92', 'BA93', 'B93', 'BA94', 'B94', 'BA95', 'B95', 'B96', 'BA96', 'BA97', 'B97', 'B98', 'BA98', 'BA99', 'B99', 'BA100', 'B100']

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

アルファベット一文字と数値の組み合わせなら、次のように書けるかと。

>>> import random
>>>
>>> A = ['A' + str(i) for i in range(1, 11)]
>>> B = ['B' + str(i) for i in range(1, 11)]
>>>
>>> AB = A + B
>>> random.shuffle(AB)
>>>
>>> print(AB)
['B3', 'A4', 'A7', 'B7', 'A10', 'B5', 'A1', 'B9', 'A5', 'A9', 'B10', 'A3', 'A6', 'A2', 'B2', 'B4', 'B1', 'B6', 'A8', 'B8']
>>>
>>> AB.sort(key=lambda x: (int(x[1:]), x[0]))
>>> print(AB)
['A1', 'B1', 'A2', 'B2', 'A3', 'B3', 'A4', 'B4', 'A5', 'B5', 'A6', 'B6', 'A7', 'B7', 'A8', 'B8', 'A9', 'B9', 'A10', 'B10']

アルファベットが複数文字のときは、次のような関数を作ると良さそうですね。
(その気になればindex errorやrecursion errorを起こせますが、普通に使う分には問題ないです。)

def find_first_num(arg, i=0):
    if not arg[0].isalpha():
        return i
    return find_first_num(arg[1:], i+1)

こんな風に、英字と数字を分離できます。

>>> hoge = 'LouiS0616'
>>> hoge[:find_first_num(hoge)]
'LouiS'
>>> hoge[find_first_num(hoge):]
'0616'

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • Python 3.x

    4134questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。