簡體   English   中英

使用另一個列表在Python列表中對字符串進

[英]Sort strings in Python list using another list

說我有以下列表:

List1=['Name1','Name3','Color1','Size2','Color3','Color2','Name2','Size1', 'ID']
List2=['ID','Color1','Color2','Size1','Size2','Name1','Name2']

每個列表將具有名為“ID”變量的元素,然后是3個其他類別(名稱,顏色和大小),其中每個類別中具有未確定數量的元素。

我想對這些變量進行排序,而不知道每個類別中將包含以下“排序列表”的數量:

SortList=['ID','Name','Size','Color']

我可以得到所需的輸出(見下文),雖然我想有更好/更pythonic的方式這樣做。

>>> def SortMyList(MyList,SortList):       
...     SortedList=[]       
...     for SortItem in SortList:
...         SortItemList=[]
...         for Item in MyList:
...             ItemWithoutNum="".join([char for char in Item if char.isalpha()])  
...             if SortItem==ItemWithoutNum:
...                 SortItemList.append(Item)
...         if len(SortItemList)>1:
...             SortItemList=[SortItem+str(I) for I in range(1,len(SortItemList)+1)]
...         for SortedItem in SortItemList:
...             SortedList.append(SortedItem)
...     return SortedList
... 
>>> 
>>> SortMyList(List1, SortList)
['ID', 'Name1', 'Name2', 'Name3', 'Size1', 'Size2', 'Color1', 'Color2', 'Color3']
>>> SortMyList(List2, SortList)
['ID', 'Name1', 'Name2', 'Size1', 'Size2', 'Color1', 'Color2']
>>> 

有關如何改進我的方法或代碼的任何建議?

您可以使用自定義鍵功能對列表進行排序,該功能返回2元組,用於主要排序和二級排序。

主要排序是按照“標簽”的順序排列的(首先是ID,然后是名稱等)。 二級排序是通過它后面的數值。

tags = ['ID','Name','Size','Color']
sort_order = { tag : i for i,tag in enumerate(tags) }

def elem_key(x):
    for tag in tags:
        if x.startswith(tag):
            suffix = x[len(tag) : ]
            return ( sort_order[tag],
                     int(suffix) if suffix else None )
    raise ValueError("element %s is not prefixed by a known tag. order is not defined" % x)

list1.sort(key = elem_key)

您只需提供足夠的密鑰:

List1.sort( key = lambda x : ('INSC'.index(x[0]),x[-1]))
# ['ID', 'Name1', 'Name2', 'Name3', 'Size1', 'Size2', 'Color1', 'Color2', 'Color3']

元素將按第一個字母排序,然后按最后一個數字排序(如果存在)。 它適用於此,因為所有首字母都不同,如果數字最多只有一位數。

編輯

對於許多數字,一個更混淆的解決方案:

List1.sort( key =lambda x : ('INSC'.index(x[0]),int("0"+"".join(re.findall('\d+',x)))))
 # ['ID', 'Name1', 'Name2', 'Name10', 'Size1', 'Size2', 'Color1', 'Color2', 'Color3']

是否(在這種情況下)比簡單的正則表達式更容易從字符串中提取數據?

import re

def keygen(sort_list):
    return lambda elem: (
        sort_list.index(re.findall(r'^[a-zA-Z]+', elem)[0]),
        re.findall(r'\d+$', elem)
    )

用法:

   SortList = ['ID', 'Name', 'Size', 'Color']
   List1 = ['Name1', 'Name3', 'Color1', 'Size2', 'Color3', 'Color2','Name2', 'Size1', 'ID']
   List2 = ['ID', 'Color1', 'Color2', 'Size1', 'Size2', 'Name1', 'Name2']
   sorted(List1, key=keygen(SortList))
=> ['ID', 'Name1', 'Name2', 'Name3', 'Size1', 'Size2', 'Color1', 'Color2', 'Color3']
   sorted(List2, key=keygen(SortList))
=> ['ID', 'Name1', 'Name2', 'Size1', 'Size2', 'Color1', 'Color2']

說明:

^[a-zA-Z]+匹配開始處的字母部分,以及字符串末尾的\\d$ - 數字部分。

keygen返回帶有字符串的lambda ,並返回兩項元組:
第一項是列表中字母部分的位置(list = ValueError沒有這樣的項目),
第二個是包含末尾數字部分的單項列表,如果字符串不以數字結尾,則為空列表。

一些可能的改進:

  • sort_list.index調用是O(n) ,它將被調用列表中的每個元素; 可以用O(1) dict查找替換以加快排序(我沒有這樣做以保持簡單),
  • 數字部分可以被賦予實際整數( 1 < 2 < 10 ,但'1' < '10' < '2'

申請后:

import re

def keygen(sort_list):
    index = {(word, index) for index, word in enumerate(sort_slist)}
    return lambda elem: (
        index[re.findall(r'^[a-zA-Z]+', elem)[0]],
        [int(s) for s in re.findall(r'\d+$', elem)]
    )

只要您知道List2只包含以sortList中的內容開頭的字符串,這就可以工作

List2=['ID','Color4','Color2','Size1','Size2','Name2','Name1']
sortList=['ID','Name','Size','Color']
def sort_fun(x):
    for i, thing in enumerate(sortList):
        if x.startswith(thing):
            return (i, x[len(thing):])

print sorted(List2, key=sort_fun)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM