[英]Python: Sort list of lists by size (reversed) and store the original indices
[英]Python sort a list of lists by occurrence and reversed order
我有以下列表
list_55 = [[1,2],[2,1],[3,4],[5,6],[4,3],[1,2],[1,2],[6,5],[6,5]]
我想像這樣對這個列表進行排序。 以便列表按降序排列和倒序排列。 例如:
[1,2],[1,2],[1,2] followed by [2,1]
[6,5],[6,5] followed by [5,6]
[4,3] followed by [3,4] The order of this last one doesn't matter.
output:
[[1,2],[1,2],[1,2],[2,1],[6,5],[6,5],[5,6],[4,3],[3,4]]
我試過了:
sorted(list_55, key=list_55.count, reverse=True)
這使:
[[1, 2], [1, 2], [1, 2], [6, 5], [6, 5], [2, 1], [3, 4], [5, 6], [4, 3]]
和
sorted(list_55,reverse=True)
給出:
[[6, 5], [6, 5], [5, 6], [4, 3], [3, 4], [2, 1], [1, 2], [1, 2], [1, 2]]
我想要這兩者的結合。 有沒有辦法做到這一點?
嘗試:
print(
sorted(
list_55,
key=lambda l: (
list_55.count(l) + list_55.count(l[::-1]),
list_55.count(l),
),
reverse=True,
)
)
印刷:
[[1, 2], [1, 2], [1, 2], [2, 1], [6, 5], [6, 5], [5, 6], [3, 4], [4, 3]]
使用:=
的更高效的解決方案:
print(
sorted(
list_55,
key=lambda l: (
(cnt := list_55.count(l)) + list_55.count(l[::-1]),
cnt,
),
reverse=True,
)
)
為了獲得更高的性能,使用functools.lru_cache
的版本:
from timeit import timeit
from functools import lru_cache
from collections import defaultdict, Counter
list_55 = [
[1, 2],
[2, 1],
[3, 4],
[5, 6],
[4, 3],
[1, 2],
[1, 2],
[6, 5],
[6, 5],
]
def fn1(lst):
@lru_cache(maxsize=None)
def key_fn(l):
cnt = lst.count(l)
return cnt + lst.count(l[::-1]), cnt
lst[:] = map(tuple, lst)
return sorted(
lst,
key=key_fn,
reverse=True,
)
def fn2(l):
dct = defaultdict(Counter)
for lst in l:
dct[frozenset(lst)].update({tuple(lst): 1})
# counters_sorted = sorted(
# dct.values(), key=lambda c: c.total(), reverse=True
# )
counters_sorted = sorted(
dct.values(), key=lambda c: sum(c.values()), reverse=True
) # for python < 3.10
return [
tup
for counter in counters_sorted
for tup, n in counter.most_common()
for _ in range(n)
]
t1 = timeit(
"fn1(lst)", setup="lst = list_55 * 1000", number=1, globals=globals()
)
t2 = timeit(
"fn2(lst)", setup="lst = list_55 * 1000", number=1, globals=globals()
)
print(t1)
print(t2)
打印(AMD 3700x/Python 3.9):
0.0037845000624656677
0.011112367967143655
另一種選擇是使用collections.Counter
,我想當輸入列表很長時效率更高:
from collections import defaultdict, Counter
list_55 = [[1,2],[2,1],[3,4],[5,6],[4,3],[1,2],[1,2],[6,5],[6,5]]
dct = defaultdict(Counter)
for lst in list_55:
dct[frozenset(lst)].update({tuple(lst): 1})
counters_sorted = sorted(dct.values(), key=lambda c: c.total(), reverse=True)
# counters_sorted = sorted(dct.values(), key=lambda c: sum(c.values()), reverse=True) # for python < 3.10
output = [tup for counter in counters_sorted
for tup, n in counter.most_common()
for _ in range(n)]
print(output)
# [(1, 2), (1, 2), (1, 2), (2, 1), (6, 5), (6, 5), (5, 6), (3, 4), (4, 3)]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.