根据另一个按步骤排序的列表对列表进行排序

时间:2019-07-10 14:45:55

标签: python list sorting sublist

我正在尝试根据列表{% for item in menu_items %} <li> <a href="{% if item.specific.link and item.specific.link != '' %}{{ item.specific.link }}{% elif item.specific_class == 'Node'%}#{% else %}{% pageurl item %}{% endif %}">{{ item.title } </a> </li> {% endfor %} 的排序来对列表B进行排序。棘手的部分是列表A的排序是分步进行的。 我曾尝试压缩列表,但无法正常工作。

列表A的排序是这样的:

A

正在发生以下情况:

steps = [0, 1, 3, 5] B = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] A = [['X', 'Y'], ['X'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X'], ['X', 'Y', 'Z'], ['X', 'Y'] for i in range(len(steps)-1): A[steps[i]:steps[i + 1]] = sorted(A[steps[i]:steps[i + 1]], key = len, reverse=True) 中的

子列表0根据长度以相反的顺序排序,然后是子列表1,2,然后是3,4,最后是5,6。

2 个答案:

答案 0 :(得分:1)

您可以使用zip对列表进行排序,只需要一个可以解释这些对的键函数即可。然后,在对对进行排序后,您可以使用zip“解压缩”它们

B = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
A = [['X', 'Y'], ['X'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X'], ['X', 'Y', 'Z'], ['X', 'Y']]
def lenRight(pair):
    return len(pair[1])
C = sorted(zip(B,A), key = lenRight)

B_sorted, A_sorted = zip(*C)
print(B_sorted)
print(A_sorted)

这将输出:

('B', 'E', 'A', 'G', 'C', 'D', 'F')
(['X'], ['X'], ['X', 'Y'], ['X', 'Y'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'])

编辑:

我现在明白了,

steps = [1, 3, 5]
B = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
A = [['X', 'Y'], ['X'], ['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X'], ['X', 'Y', 'Z'], ['X', 'Y']]

lastStep = 0
sortedLists = []

def lenRight(pair):
        return len(pair[1])

for step in steps:
    C = sorted(zip(B[lastStep:lastStep+step],A[lastStep:lastStep+step]), key = lenRight, reverse = True)

    B_sorted, A_sorted = zip(*C)
    sortedLists.append((A_sorted, B_sorted))

    lastStep = step

for pair in sortedLists:
    A_sort, B_sort = pair
    print(A_sort, B_sort)

输出:

(['X', 'Y'],) ('A',)
(['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X']) ('C', 'D', 'B')
(['X', 'Y', 'Z'], ['X', 'Y', 'Z'], ['X', 'Y'], ['X']) ('D', 'F', 'G', 'E')

答案 1 :(得分:1)

假设A中的所有对象都是可哈希的且唯一的:

  1. AB一起压缩到列表C中,并将该列表移到一边。
  2. 使用基于神秘步骤的算法对A进行排序。不用担心BC
  3. 排序完成后,建立一个A项的反向查找字典,将其放在排序算法所处的位置。
  4. 使用该反向查找和压缩列表对B进行排序。
A = [29, 42, 17]
B = ['bravo', 'charlie', 'alpha']
C = list(zip(A, B))
A.sort() # replace with your mystery sorter
lookup = {a:index for (index, a) in enumerate(A)}

for  (a, b) in C:
    index = lookup[a]
    B[index] = b

print(A)
print(B)
#output
[17, 29, 42]
['alpha', 'bravo', 'charlie']

构建C,构建查找字典以及最后组织B的成本都是O(n)

免责声明:不喜欢写回B。宁愿写一个大小合适的新列表。

更新:上面的代码仅在A中没有重复项时有效。下面的代码段通过附加一个唯一性(原始索引)来处理重复项。尽管这行得通,但是这种方法太复杂了。您也可以将A和B的邮政编码排序在一起,这在另一个答案中进行了描述。

A = [29, 42, 29, 17]
B = ['bravo1', 'charlie', 'bravo2', 'alpha']
A2 = [(index, a) for index,a in enumerate(A)]
C = list(zip(A, B))
A2.sort(key=lambda t : t[1] ) # replace with your mystery sorter, which has to deal with tuples now
A = [a for (_, a) in A2]
lookup = {t:index for (index, t) in enumerate(A2)}

for  original_index, (a, b) in enumerate(C):
    new_index = lookup[original_index, a]
    B[new_index] = b

print(A)
print(B)
#output
[17, 29, 29, 42]
['alpha', 'bravo1', 'bravo2', 'charlie']

为了完整起见,下面的代码是我必须处理A中的重复项时真正要做的事情。这实质上是发布的另一个答案。

A = [29, 42, 29, 17]
B = ['bravo1', 'charlie', 'bravo2', 'alpha']
C = list(zip(A, B))
C.sort(key=lambda t : t[0] ) # replace with your mystery sorter, which has to deal with a zip of A and B together
[A, B] = zip(*C)

print(A)
print(B)