簡體   English   中英

基於另一個較短列表的列表排序

[英]List sort based on another shorter list

我需要根據另一個更短的列表中元素的順序對列表進行排序,即與我正在排序的列表相比,沒有所有元素。 使用sort(key=short_list)時遇到此錯誤:

long_list = ['y', 'z', 'x', 'c', 'a', 'b']
short_list = ['b', 'c', 'a']
long_list.sort(key=short_list.index)

ValueError: 'x' is not in list

是否有另一種方法對long_list進行排序以long_list一個保持short_list順序的list ,然后是short_list中元素的long_list

['b', 'c', 'a', 'y', 'z', 'x']

這樣的事情應該工作:

def position(value):
    try:
        return short_list.index(value)
    except ValueError:
        return len(short_list)

long_list.sort(key=position)

排序保證是穩定的,因此使用len(short_list)確保未知值排在最后。

您可以使用in來檢測元素是否在 short_list 和三元組中以基於該元素返回元組。:

>>> long_list = ['y', 'z', 'x', 'c', 'a', 'b']
>>> short_list = ['b', 'c', 'a']
>>> sorted(long_list, key=lambda e: (short_list.index(e),e) if e in short_list  else (len(short_list),e))
['b', 'c', 'a', 'x', 'y', 'z']

由於 Python 排序是穩定的,因此順序只會根據元素本身的變化而變化。 為了進行這種更改,我們可以使用帶有(index_of_the_element, element)(len(short_list), element)來實現該更改。

如果您希望元素不在短列表中時不改變順序,只需返回一個空元組:

>>> sorted(long_list, key=lambda e: (short_list.index(e),e) if e in short_list  else (len(short_list),))
['b', 'c', 'a', 'y', 'z', 'x']

如果需要,我會先在短名單中搜索,然后在長名單中搜索:

>>> def index(list1, list2):
...  def inner(value):
...   try:
...    return list1.index(value)
...   except ValueError:
...    return list2.index(value)
... 
>>> long_list = ['x', 'y', 'z', 'a', 'b', 'c']
>>> short_list = ['a', 'b', 'c']
>>> long_list.sort(key=index(short_list, long_list))
>>> long_list
['a', 'b', 'c', 'x', 'y', 'z']

編輯:正如 florian-weimer 指出的那樣,這個解決方案並不總是有效。 加入兩種解決方案:

>>> def index(list1, list2):
...  def inner(value, l=len(list1)):
...   try:
...    return list1.index(value)
...   except ValueError:
...    return l
...  return inner
... 
>>> long_list = ['x', 'y', 'z', 'a', 'b', 'c']
>>> short_list = ['a', 'b', 'c', 'y']
>>> sorted(long_list, key=index(short_list, long_list))
['a', 'b', 'c', 'y', 'x', 'z']
>>> 

基本上,我在這里做的是首先按 long_list 中的索引對 long_list 的元素進行排序。 如果該元素不在 short_list 中,我將為它們分配與 len(short_list) 相同的值。 排序時,如果兩個元素的 first_sort 相同,則按照 long_list 中的位置 second_sort 進行排序。 讓我們看看每個案例

  1. 'a'、'b' 和 'c' 都按它們在 short_list 中的位置排序。 如果long_list中有'a'、'b'或'c'的重復,則按各自的位置排序。 所以你會得到 ['b', 'c', 'c', 'a', 'a', 'a']。
  2. 'y', 'z', 'x' 首先按 len(short_list) 排序。 與短列表中的元素相比,這將它們放在最后。 然后它們按照它們在 long_list 中的順序進行排序。

關鍵要點:

  1. 您可以將一個函數傳遞給 key,讓您可以根據任何函數進行排序。
  2. 您可以傳遞一個返回多個值的函數,以便第一個值中的任何關系都由第二個值解析,依此類推。
long_list = ['y', 'z', 'x', 'c', 'a', 'b']
short_list = ['b', 'c', 'a']

def sorter(x):
    if x in short_list:
        first_sort = short_list.index(x)
    else:
        first_sort = len(short_list)
    second_sort = long_list.index(x)
    return first_sort, second_sort

print(sorted(long_list, key=sorter)) 
['b', 'c', 'a', 'y', 'z', 'x']

暫無
暫無

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

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