4

(文字列)タイヤサイズのリストを最小から最大に並べ替えようとしています。

['285/30/18',
 '285/30/19',
 '235/40/17',
 '315/25/19',
 '275/30/19']

次のように並べ替える必要があります。

['235/40/17',
 '285/30/18',
 '315/25/19'
 '275/30/19',
 '285/30/19']

基本的に、文字列を右、中央、左の順に並べ替える必要があります。

私がこれまでに持っているもの(バブルソート):

# this sorts the first numbers on the right.
nums = list(ulst)
for i in range(len(nums)):
     for j in range(i+1, len(nums)):
         if ulst[j].split('/')[2] < ulst[i].split('/')[2]:
             ulst[j], ulst[i] = ulst[i], ulst[j]

右の行の並べ替えを台無しにせずに真ん中を並べ替え、次に左の行を並べ替える必要があります....

for/if ネストされた混乱を作成せずにこれを解決するにはどうすればよいですか?

4

7 に答える 7

10

Python には、これを簡単に行うための機能がいくつかあります。実際、すべてを 1 つのステートメントで実行できます。

sorted(nums, key=lambda x: tuple(reversed(list(map(int, x.split("/"))))))

x.split("/")各値を受け取り、文字列のリストを作成します。

["235", "40", "17"]

を使用map(int, ...)すると、整数のリストが得られます。

[235, 40, 17]

reversed()それを好転させる:

[17, 40, 235]

それをタプルにtuple()変換します。

(17, 40, 235)

他の同様のタプルと比較すると、必要な並べ替え順序が得られます。

于 2012-12-27T07:19:18.963 に答える
1

str.splitreversed、およびの構成を使用して、 でtuple使用するキー関数を作成しますsorted

sizes = ['285/30/18',
         '285/30/19',
         '235/40/17',
         '315/25/19',
         '275/30/19']

s = sorted(sizes, key=lambda z: tuple(reversed([int(i) for i in z.split("/")])))

sorted 関数はシーケンスとキー関数を取り、リストの各項目のキー関数の戻り値でソートされたシーケンスの項目のリストを返します。このキー関数 はlambda z、最初に「/」文字でアイテムを分割して文字列のリストを作成します。次に、それぞれが数値に変換され、reversed渡されたシーケンスの逆順のイテレータを提供する関数に渡されます。 (注: これはまだ評価されていません)、tuple関数は逆反復子を評価し、並べ替えに使用できるシーケンスに変換します。

したがって、「a/b/c」のようにフォーマットされた一連の文字列は、(c, b, a) でソートされて返されます。これにより、次の結果が得られます。

>>> print s
['235/40/17', '285/30/18', '315/25/19', '275/30/19', '285/30/19']
于 2012-12-27T07:31:54.370 に答える
1

value1 つの方法は、正しい順序で 3 つのフィールドを考慮して、次の関数を使用してソート キーを作成することです。

def value(s):
    arr = s.split('/')
    return arr[2] * 100000 + arr[1] * 1000 + arr[0]

ulst = ['285/30/18', '285/30/19', '235/40/17', '315/25/19', '275/30/19']

for i in range(len(ulst)):
     for j in range(i+1, len(ulst)):
         if value(ulst[j]) < value(ulst[i]):
             ulst[j], ulst[i] = ulst[i], ulst[j]

print ulst

その出力は、必要に応じて次のとおりです。

['235/40/17', '285/30/18', '315/25/19', '275/30/19', '285/30/19']

タイヤのサイズが指定された 3/2/2 桁であれば、これは問題なく機能します。これはかなり安全な賭けです。12 インチ未満のタイヤは見たことがなく、100 インチのタイヤはおそらく大きすぎて乗れません :-)

于 2012-12-27T07:18:59.963 に答える
1

良い答えがたくさん。単なる例として、または簡単な 1 回限りの解析、または宿題の割り当てのためにこれを行っている場合、これらはすべて、文字列の処理/並べ替えが適切であることを示しています。しかし、タイヤ管理に関する実際のアプリを実際に構築している場合は、タイヤの実際のモデルを作成することを検討します。

from ast import literal_eval
from operator import attrgetter

# Make a real object, because we can, and it's easy, and a real object is almost always better than abusing literal types
class Tire(object):
    def __init__(self, width = 0, profile = 0, radius = 0): #now we have meaningful names to our indexed fields
        self.width = width
        self.profile = profile
        self.radius = radius

    # let's encapsulate the '{width}/{profile}/{radius}' string representation
    # as an attribute so we can access/set it like the "real" attributes
    @property
    def description(self):
        return '{}/{}/{}'.format(self.width, self.profile, self.radius)

    @description.setter
    def description(self, string):
        self.width, self.profile, self.radius = map(literal_eval, string.split('/')) #ast.literal_eval() is safer than just eval()

    # let's make a class side instance creation method that can instantiate and set the description directly too
    @classmethod
    def fromDescription(me, descriptionString):
        newTire = me()
        newTire.description = descriptionString
        return newTire

#your original sample input     
descriptions = ['285/30/18', '285/30/19', '235/40/17', '315/25/19', '275/30/19']

#now lets make some real tire objects from those
tires = [Tire.fromDescription(each) for each in descriptions]

#make sure they still print
[print(each.description) for each in tires]

print('original sort')
[print(each.description) for each in sorted(tires, key = attrgetter('radius'))]

print('reversed original sort')
[print(each.description) for each in sorted(tires, key = attrgetter('radius'), reverse = True)]

print('width sort')
[print(each.description) for each in sorted(tires, key = attrgetter('width'), reverse = True)]

print('radius>>width>>profile sort')
[print(each.description) for each in sorted(tires, key = attrgetter('radius', 'width', 'profile'))]

このアプローチの価値は、最後に明らかになることを願っています。タイヤ オブジェクトを具体化するために、(コード スペースの点で) 前もって大きな代償を払います。しかし、それができたら、あらゆる種類の方法でそれらを並べ替えることから始めることができます。最初に提示されたアルゴリズムは、文字列表現と目的の並べ替え出力を結合する特定の仮定を考えると、うまく機能します。しかし、最後の行のように (フィールド 3、1、2 でソートするために) ソート出力を変更する必要がある場合、タプルの便利な逆のトリックは機能しなくなります。「それが何であるか」と、それをどのように提示(ソート)するかを分離する方がはるかに優れています(IMO)。そして、それらを並べ替えるだけでなく、後でそれらを処理するためのさらにいくつかの賢い方法を考えるかもしれません.

于 2012-12-27T19:38:53.700 に答える
0
    python 3.2

    sorted(list1,key=lambda x:x[-2:])
于 2012-12-27T16:49:21.363 に答える
0

この Q/A は、私自身の問題を解決するための指針を与えてくれました - 他の人に知らせるために追加しました。
次の形式の *nix ディレクトリのリストを持つ: /home/0000/Maildir/<0-255>/<userdirs>

0000 - 4 桁の一意のプロバイダー名
<0-255> - 範囲

リストのサイズは、3000 から 250000 アイテムまでさまざまです。

各項目を「/」で区切って、4 番目のフィールドで数値ソートを使用してリストをソートする必要がありました

sorted(a, key=lambda y: int(y.split("/")[4]))
于 2013-02-06T08:54:45.110 に答える
0

sの位置/が一定の場合は、次を試してください。

sorted(a, key=lambda x:x[-2:]+x[4:6]+x[:3])

http://ideone.com/M6X6pW

于 2012-12-27T07:22:35.240 に答える