[英]Sort list of real numbers mixed with letters
我有一個必須排序的數據列表,遺憾的是這些對象的命名方案不是很一致。 數據是一個字符串列表,通常是實數,但有時最后會有一個字母。 此列表中可接受值的一些示例如下所示:
# 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']
遺憾的是,它無法對它進行排序。 所以我的新計划是編寫一個可以使用python sorted
方法的方法,但我仍然不確定如何編寫它。 我需要找到一種方法,按字符串的實數部分排序,然后作為輔助排序,按附加到結尾的字母排序。
關於去哪里的任何建議?
讓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;
完全按照要求訂購,也快速訂購。 帶有ARRAY
和unnest()
的子選擇僅用於構建快速測試用例。 ORDER BY
子句是重要的 - 手冊中的rtrim()
。
如果涉及其他字符,您可能需要更新問題以完成圖片。
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']
我在結尾處過早概括為任意數量的字母:
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)
將字符串拆分為元組 - 實數(將其轉換為浮點數或十進制數)和通常為空的字符串。 如果你對元組進行排序,並使用python的內置排序(timesort),它應該非常快。
如果您的實物中允許使用科學記數法,請注意,例如1e10。
如果有任何機會,以后比較會有額外的復雜性,請使用類而不是元組。 但元組可能會更快。 然后定義一個或多個比較函數(取決於你是否在python 2.x或3.x)。
元組比較元素0,然后是元素1等。
您的類替代方案需要具有cmp方法或3.x等效方法。
將字符串存儲為字符串然后解析它以對其進行排序似乎是錯誤的方法。 如果你真的擁有它
然后我強烈建議將其存儲為兩個整數和一個文本字段。 對major_number,minor_number進行排序,修訂版將完全按預期工作。 您可以將asnumber定義為數據庫級別的視圖,也可以定義為基於具有關聯__cmp__()
的三個基本數字的類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.