我正在创建所有可能的排列,包括从0到给定数字的三个元素:
for i in itertools.permutations(range(len(atoms)), 3):
if i[0] < i[-1]:
angles = list(i)
条件避免在我的列表上同时具有(0,1,2)和(2,1,0)“角度”,这已经很棒了。现在,我需要将此列表分成由具有相同中心元素的“角度”组成的较小组。 通过这种方式,我有:
A = ([0, 1, 2], [0, 1, 3], [3, 1, 4])...
B = ([0, 2, 3], [0, 2, 4], [3, 2, 4])...
等等。
你能帮帮我吗?
答案 0 :(得分:2)
您可以使用defaultdict
对排列进行分组:
from collections import defaultdict
angles = defaultdict(list)
for i in itertools.permutations(range(len(atoms)), 3):
if i[0] < i[-1]:
angles[i[1]].append(i)
如果len(atoms)
为4,那么您将获得以下结果:
defaultdict(<type 'list'>, {
0: [(1, 0, 2), (1, 0, 3), (2, 0, 3)],
1: [(0, 1, 2), (0, 1, 3), (2, 1, 3)],
2: [(0, 2, 1), (0, 2, 3), (1, 2, 3)],
3: [(0, 3, 1), (0, 3, 2), (1, 3, 2)]
})
答案 1 :(得分:1)
itertools.groupby
函数可用于创建包含相同中心元素的列表,但您必须先对列表进行排序,以便具有相同中心元素的排列彼此相邻。为此,您需要向sort
和groupby
传递一个查看中心元素的关键函数。一种方法是这样的:
def keyfunc(s):
return s[1]
或者,作为一个lambda:
keyfunc = lambda s: s[1]
或者您可以使用itemgetter
模块中的operator
,该模块简洁且明显快于使用lambda
或def
功能。
以下代码基于您的代码,但它会在列表推导中创建初始列表。然后它将组放在字典中,中心元素为dict
键。
from itertools import permutations, groupby
from operator import itemgetter
atoms = 'abcd'
perms = permutations(range(len(atoms)), 3)
angles = [list(u) for u in perms if u[0] < u[-1]]
keyfunc = itemgetter(1)
angles.sort(key=keyfunc)
print(angles)
groups = {k: list(g) for k, g in groupby(angles, keyfunc)}
print(groups)
<强>输出强>
[[1, 0, 2], [1, 0, 3], [2, 0, 3], [0, 1, 2], [0, 1, 3], [2, 1, 3], [0, 2, 1], [0, 2, 3], [1, 2, 3], [0, 3, 1], [0, 3, 2], [1, 3, 2]]
{0: [[1, 0, 2], [1, 0, 3], [2, 0, 3]], 1: [[0, 1, 2], [0, 1, 3], [2, 1, 3]], 2: [[0, 2, 1], [0, 2, 3], [1, 2, 3]], 3: [[0, 3, 1], [0, 3, 2], [1, 3, 2]]}
答案 2 :(得分:1)
虽然上述答案为更一般的问题提供了出色的解决方案,但只需3个元素就可以选择列表理解就足够了。
atoms = [0, 1, 2, 3]
angles = [[(a, b, c) for i, a in enumerate(atoms, start=1) if a != b
for c in atoms[i:] if c != b] for b in atoms]
# [[(1, 0, 2), (1, 0, 3), (2, 0, 3)],
# [(0, 1, 2), (0, 1, 3), (2, 1, 3)],
# [(0, 2, 1), (0, 2, 3), (1, 2, 3)],
# [(0, 3, 1), (0, 3, 2), (1, 3, 2)]]
它比我的机器上的排列+ groupby方法快约40%。
答案 3 :(得分:0)
您可以考虑itertools.groupby
:
from itertools import groupby, permutations
perms = filter(lambda x: x[0] < x[-1], permutations(range(4), 3))
key = lambda x: x[1] # sort and group by second element
angles = [list(g) for k, g in groupby(sorted(perms, key=key), key=key)]
# here, any comprehension can be used, e.g.
# angles = {k: list(g) for k, g in groupby(sorted(perms, key=key), key=key)}
# will produce the dict from @niemmi's answer
>>> angles
[
[(1, 0, 2), (1, 0, 3), (2, 0, 3)],
[(0, 1, 2), (0, 1, 3), (2, 1, 3)],
[(0, 2, 1), (0, 2, 3), (1, 2, 3)],
[(0, 3, 1), (0, 3, 2), (1, 3, 2)]
]