2011-10-17 14 views
2

私は整数だけでなく名前も表すことができる文字列のリストを持っています。 デフォルトの文字列以下のんを比較:以下の方法で文字列のリストをソートする最も簡単な方法は何ですか?

sorted(['1','2','3','4','10','102','14','Alice','John','Sally']) 
['1', '10', '102', '14', '2', '3', '4', 'Alice', 'John', 'Sally'] 

私は次のようにリストをソートしたいと思います:

  1. をソートすべての数値の整数を表す文字列を:意味

    ['1', '2', '3', '4', '10', '14', '102', 'Alice', 'John', 'Sally'] 
    

  2. '実際の'文字列をアルファベット順に並べ替え、このリストを(1)に追加します。

私は比較方法を試しましたが、文字列がtry/exceptなしの整数を表すかどうかを正確に判断する方法はわかりません。

事前

答えて

10

のおかげで何の負の数が存在しない場合:

lyst = ['1','2','3','4','10','102','14','Alice','John','Sally'] 
print sorted(lyst, key=lambda k: int(k) if k.isdigit() else k) 

ここではCPythonの詳細に依存しないバージョンだとPython 3で動作します。

ここ
sorted(lyst, key=lambda k: (0, int(k)) if k.isdigit() else (1, k)) 

キーはタプルです。タプルの最初の項目は、数値またはテキストの場合は0または1で、数値がテキストの前にソートされます。タプルの2番目の項目は値で、その値はグループ内で適切にソートされます。私は当初、数字の後にテキスト項目を並べ替えるためにfloat("+inf")を使用しましたが、このアプローチ(Tom Zychの答えに触発されています)はより簡単で高速です。

あなたは文字列は大文字と小文字を区別できないために並べ替えたい場合は、単に.lower()を追加します。

sorted(lyst, key=lambda k: (0, int(k)) if k.isdigit() else (1, k.lower())) 
+0

おかげで、私がまさに必要! (私の場合、負の数はありません) – any1

+4

これは、(1)CPtyhonの実装の詳細に依存していることに注意してください。 (2)は、文字列との比較が許可されていないため、Python 3では動作しません。 – NPE

+0

良い点、別のバージョンを追加しました。 – kindall

5

のPython 2とPython 3の両方で、次の作品を:

l = ['1','2','3','4','10','102','14','Alice','John','Sally','33'] 
num, alpha = [], [] 
[num.append(elem) if elem.isdigit() else alpha.append(elem) for elem in l] 
result = sorted(num, key=int) + sorted(alpha) 
print(result) 

それはへの文字列を比較回避リストを分割することによって整数を返します。そのような比較を避ける理由は、not fully specified(Python 2)または禁止(Python 3)のいずれかです。

+0

+1。私はこれが2と3で動作するのが好きです。簡単に避けることができるので、私はブール値で添え字が好きではありません。リストcompを 'elem.isdigit()else.append(elem)if elem in l 'に変更します。また、1行をスナップすることもできます。 –

+0

@StevenRumbalski:良い提案、ありがとう。 – NPE

+0

賢い、upvote。 'any(...)'の中でリストの理解を使って 'None'のリストを作るのを避けることができます。 – kindall

5

これは、キー機能を持つsortのバージョンで動作するはずです。

def sortkey(s): 
    try: 
     n = int(s) 
     return (0, n) 
    except ValueError: 
     return (1, s) 
+0

これはタプルが辞書編集的に比較されるために機能します。最初の項目が比較されます。同じ場合は2番目の項目が比較され、以下同様です。非常に素晴らしい。 –

+0

この作業をPython 3にするには、整数の場合は '(0、n、" ")'を、文字列の場合は '(1、0、s)'を返します。私はこれが負の数でもどのように機能するのが好きです。ただし、浮動小数点数で間違った結果が生じる可能性があります。 –

+0

@StevenRumbalski:OPは "整数"と言っていました。フロートがある場合は、もちろん、試用版を追加する必要があります。私のコードは3.1で書かれているように正しく動作するようです。なぜあなたの変更が必要だと思いますか? –

0

私は比較機能となるだろう:

import types 

def cmp_func(val1, val2): 
    # is val1 an integer? 
    try: 
    val1 = int(val1) 
    except ValueError: 
    pass # val1 is no integer 
    try: 
    val2 = int(val2) 
    except ValueError: 
    pass #val2 is no integer 

    if type(val1) == types.IntType and type(val2) == types.IntType: 
    return cmp(val1, val2) 
    elif type(val1) == types.StringType and type(val2) == types.IntType: 
    # firstly strings, afterwards integer values 
    return -1 
    elif type(val1) == types.IntType and type(val2) == types.StringType: 
    # firstly strings, afterwards integer values 
    return 1 
    else: 
    return cmp(val1, val2) 


if __name__ == "__main__": 
    my_list = ['1', '10', '102', '14', '2', '3', '4', 'Alice', 'John', 'Sally'] 
    my_list.sort(cmp_func) 
    print(my_list) 
関連する問題