我有以下配对值列表:
a = [['A', 'B'], ['A', 'C'], ['D', 'D'], ['C', 'D']]
此列表可以包含一个或多个由同一项组成的卓越对:
['D', 'D']
我想将这些对移到列表的末尾以获取:
a = [['A', 'B'], ['A', 'C'], ['C', 'D'], ['D', 'D']]
我无法理解,但我相信我并不太远:
a.append(a.pop(x) for x in range(len(a)) if a[x][0] == a[x][1])
答案 0 :(得分:9)
直接sorting:
a = [['A', 'B'], ['A', 'C'], ['D', 'D'], ['C', 'D']]
a = sorted(a, key=lambda x: x[0] == x[1])
# [['A', 'B'], ['A', 'C'], ['C', 'D'], ['D', 'D']]
这个简单的key function有效,因为False
在True
之前排序,同时将所有对映射到只有两个键维护stability。这种方法的缺点是排序是O(N_logN)
。对于没有不必要的列表连接的线性解决方案,您可以将itertools.chain
与适当的生成器一起使用:
from itertools import chain
a = list(chain((p for p in a if p[0] != p[1]), (p for p in a if p[0] == p[1])))
答案 1 :(得分:6)
使用列表推导:
a = [pair for pair in a if pair[0] != pair[1]] + [pair for pair in a if pair[0] == pair[1]]
请注意,更有效的解决方案是
identical = []
not_identical = []
for pair in a:
if pair[0] == pair[1]:
identical.append(pair)
else:
not_identical.append(pair)
a = not_identical + identical
效率更高,因为在这里只迭代a
一次,而在列表推导解决方案中,您迭代a
两次。尽管如此,两种解决方案都需要O(n)
时间复杂度和O(n)
空间复杂度,这比排序解决方案更好(并且对于此问题更自然)。
答案 2 :(得分:0)
如果您希望原始解决方案有效,您可以做一些简单的事情:
a = [['A', 'B'], ['A', 'C'], ['D', 'D'], ['C', 'D']]
for i, pair in enumerate(a):
if pair[0] == pair[1]:
a.append(a.pop(i))
print(a)
# [['A', 'B'], ['A', 'C'], ['C', 'D'], ['D', 'D']]
这是O(N^2)
,因为for循环中的pop(i)
,O(N)
本身。如果从列表末尾弹出,pop()
仅为O(1)
。
您还可以按照列表集的长度使用字典进行分组,如果您最后避免排序,只需使用O(N)
和min()
,这两个都是max()
O(N)
次操作。
以下是一个例子:
from collections import defaultdict
a = [['A', 'B'], ['A', 'C'], ['D', 'D'], ['C', 'D']]
d = defaultdict(list)
for sublst in a:
key = len(set(sublst))
d[key].append(sublst)
result = result = d[max(d)] + d[min(d)]
print(result)
# [['A', 'B'], ['A', 'C'], ['C', 'D'], ['D', 'D']]
当然,如@schwobaseggl所示,您也可以接受O(NlogN)
排序方法:
sorted(a, key = lambda x: -len(set(x)))
答案 3 :(得分:-1)
只需收集列表中的所有重复项,最后扩展列表:
a = [['A', 'B'], ['A', 'C'], ['D', 'D'], ['C', 'D']]
no_dub=[]
dub=[]
for i in a:
if i[0]==i[1]:
dub.append(i)
else:
no_dub.append(i)
no_dub.extend(dub)
print(no_dub)
输出:
[['A', 'B'], ['A', 'C'], ['C', 'D'], ['D', 'D']]