3

並べ替える必要があるデータのリストがありますが、残念ながら、これらのオブジェクトの命名規則はあまり一貫していません。データは文字列のリストで、ほとんどの場合は実数ですが、末尾に文字が含まれることもあります。このリストで許容される値の例を次に示します。

# this is how it should be sorted
['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']

これらはデータベースにあるため、最初に考えたのは、次の django メソッドを使用してソートされた結果を返すことでしたが、次のように返されます。

#took out unneeded code
choices = [l.number for l in Locker.objects.extra(
               select={'asnumber': 'CAST(number as BYTEA)'}).order_by('asnumber')]
print choices
==> ['1', '1.1', '101.1', '101.2', '2', '2.1A', '2.1B', '2.2A']

悲しいことに、本来あるべきように並べ替えることができませんでした。したがって、私の新しい計画は、pythonsortedメソッドで動作するメソッドを作成することですが、これを作成する方法がまだわかりません。文字列の実数部分でソートする方法を見つけてから、セカンダリソートとして、最後に追加された文字でソートする必要があります。

これでどこに行くべきかについて何かアドバイスはありますか?

4

5 に答える 5

4

ソートは DBMS に任せます。これは、DBMS が得意とすることです。アプリケーションのパフォーマンスに匹敵するものはほとんどありません。

A または B が追加された小数しか得られない場合は、次のように簡単に実行できます。

SELECT *
FROM  (
   SELECT unnest(
    ARRAY['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']) AS s
   ) x
ORDER  BY rtrim(s, 'AB')::numeric, s;

注文は要求どおりに、しかも迅速です。ARRAYandを使用した副選択unnest()は、簡単なテストケースを作成するためのものです。ORDER BY句は重要です -マニュアルrtrim()

他のキャラクターが関係している場合は、質問を更新して画像を完成させることをお勧めします。

于 2012-04-25T00:40:09.890 に答える
2
x = ['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']

#sort by the real number portion

import string

letters = tuple(string.ascii_letters)

def change(x):
    if x.endswith(letters):
        return float(x[:len(x) -1])
    else:
        return float(x)

my_list = sorted(x, key = lambda k: change(k))

結果:

>>> my_list
['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']
于 2012-04-24T23:04:39.080 に答える
0

文字列を文字列として保存し、それを解析して並べ替えるのは、間違ったアプローチのようです。あなたが本当に持っているものがあれば

  • メジャー番号
  • マイナー番号
  • オプションのリビジョン

次に、2つの整数とテキストフィールドとして保存することを強くお勧めします。major_number、minor_number、リビジョンでの並べ替えは、期待どおりに機能します。asnumberは、データベースレベルのビューとして定義することも、に関連付けられた3つの基本番号に基づくクラスとして定義することもできます__cmp__()

于 2012-04-24T23:49:40.727 に答える
0

私は時期尚早に最後に任意の量の文字に一般化しました:

from itertools import takewhile

def sort_key(value):
    cut_point = len(value) - len(list(takewhile(str.isalpha, reversed(value))))
    return (float(value[:cut_point]), value[cut_point:])

sorted((
    l.number
    for l in Locker.objects.extra(select={'asnumber': 'CAST(number as BYTEA)'})
), key = sort_key)
于 2012-04-24T22:53:03.470 に答える
0

文字列をタプルに分割します - 実数 (float または decimal に変換) と、多くの場合空の文字列です。タプルをソートし、Python の組み込みソート (タイムソート) を使用すると、非常に高速になるはずです。

1e10 のように、実数で科学表記が許可されている場合は注意してください。

後で比較がさらに複雑になる可能性がある場合は、タプルの代わりにクラスを使用してください。ただし、タプルの方が高速になる可能性があります。次に、1 つ以上の比較関数を定義します (Python 2.x または 3.x のどちらを使用しているかによって異なります)。

タプルは要素 0 を比較し、次に要素 1 を比較します。

クラスの代替には、cmpメソッドまたは 3.x に相当するものが必要です。

于 2012-04-24T23:03:44.010 に答える