为给定的键函数生成所有可能的等价排序
Produce all possible equivalent sorts for a given key function
说我有积分:
points = [(1., 1.), (3., 0.), (-1., -1.), (9., 2.), (-4., 2.) ]
如果我按 y 轴对它们进行排序:
points = sorted(points , key=lambda k: [k[1], k[0]])
我明白了
points = [(-1., -1.), (3., 0.), (1.,1.) , (-4.,2.), (9., 2.)]
但是我想完全独立于 x 轴对其进行排序。 此外,我希望输出是显示两种可能排序的 2 个列表(即 y 值相等时 x 值的所有排列):
[(-1., -1.), (3., 0.), (1.,1.) , (-4.,2.),(9., 2.)]
[(-1., -1.), (3., 0.), (1.,1.) , (9.,2.), (-4.,2.)]
我有办法做到这一点吗?
仅按 x 值排序:
points = sorted(points , key=lambda k: k[1])
points
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
问题陈述:
给定等价关系(例如比较 y 坐标并忽略 x 坐标),创建所有可能的排序排列的多个列表:
解决方案:
这是解决问题的一些工作代码:
from operator import itemgetter
from itertools import groupby, product, permutations, chain
points = [(1., 1.), (3., 0.),(-1., -1.) , (9., 2.), (-4., 2.) ]
points.sort(key=itemgetter(1))
groups = [list(permutations(g)) for k, g in groupby(points, itemgetter(1))]
for t in product(*groups):
print(list(chain.from_iterable(t)))
最终结果:
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (-4.0, 2.0), (9.0, 2.0)]
解释:
初始排序仅按 y 轴对点进行排序。这使用 itemgetter() 提取字段 1.
groupby() 步骤生成具有相同 y 坐标的点组。
permutations() 步骤生成每个组的所有可能排序。
product()步骤生成每个置换组的笛卡尔积(这样每个输出都有一个来自每个置换组的元素)。
chain.from_iterable() step links consecutive tuples in the product into a single iterable which can be fed into list()做出想要的结果。
一步一步:
1) 按y坐标对点进行排序,忽略x坐标:
>>> points = [(1., 1.), (3., 0.),(-1., -1.) , (9., 2.), (-4., 2.)]
>>> points.sort(key=itemgetter(1))
>>> points
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
>>> ^-----------^-----------^-----------^-------------^ ascending y-values
2) 创建具有相同 y 坐标的点组:
>>> pprint([list(g) for k, g in groupby(points, itemgetter(1))], width=40)
[[(-1.0, -1.0)], # y = -1.0
[(3.0, 0.0)], # y = 0.0
[(1.0, 1.0)], # y = 1.0
[(9.0, 2.0), (-4.0, 2.0)]] # y = 2.0
3) 生成具有相同 y 坐标的点的所有排列:
>>> groups = [list(permutations(g)) for k, g in groupby(points, itemgetter(1))]
>>> pprint(groups)
[[((-1.0, -1.0),)], # y = -1.0
[((3.0, 0.0),)], # y = 0.0
[((1.0, 1.0),)], # y = 1.0
[((9.0, 2.0), (-4.0, 2.0)), ((-4.0, 2.0), (9.0, 2.0))]] # y = 2.0
4) 用每个排列组中的一个元素创建所有可能的序列:
>>> for t in product(*groups):
print(t)
(((-1.0, -1.0),), ((3.0, 0.0),), ((1.0, 1.0),), ((9.0, 2.0), (-4.0, 2.0)))
(((-1.0, -1.0),), ((3.0, 0.0),), ((1.0, 1.0),), ((-4.0, 2.0), (9.0, 2.0)))
5) 将每个子序列组合成一个列表:
>>> for t in product(*groups):
list(chain.from_iterable(t))
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (-4.0, 2.0), (9.0, 2.0)]
说我有积分:
points = [(1., 1.), (3., 0.), (-1., -1.), (9., 2.), (-4., 2.) ]
如果我按 y 轴对它们进行排序:
points = sorted(points , key=lambda k: [k[1], k[0]])
我明白了
points = [(-1., -1.), (3., 0.), (1.,1.) , (-4.,2.), (9., 2.)]
但是我想完全独立于 x 轴对其进行排序。 此外,我希望输出是显示两种可能排序的 2 个列表(即 y 值相等时 x 值的所有排列):
[(-1., -1.), (3., 0.), (1.,1.) , (-4.,2.),(9., 2.)]
[(-1., -1.), (3., 0.), (1.,1.) , (9.,2.), (-4.,2.)]
我有办法做到这一点吗?
仅按 x 值排序:
points = sorted(points , key=lambda k: k[1])
points
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
问题陈述:
给定等价关系(例如比较 y 坐标并忽略 x 坐标),创建所有可能的排序排列的多个列表:
解决方案:
这是解决问题的一些工作代码:
from operator import itemgetter
from itertools import groupby, product, permutations, chain
points = [(1., 1.), (3., 0.),(-1., -1.) , (9., 2.), (-4., 2.) ]
points.sort(key=itemgetter(1))
groups = [list(permutations(g)) for k, g in groupby(points, itemgetter(1))]
for t in product(*groups):
print(list(chain.from_iterable(t)))
最终结果:
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (-4.0, 2.0), (9.0, 2.0)]
解释:
初始排序仅按 y 轴对点进行排序。这使用 itemgetter() 提取字段 1.
groupby() 步骤生成具有相同 y 坐标的点组。
permutations() 步骤生成每个组的所有可能排序。
product()步骤生成每个置换组的笛卡尔积(这样每个输出都有一个来自每个置换组的元素)。
chain.from_iterable() step links consecutive tuples in the product into a single iterable which can be fed into list()做出想要的结果。
一步一步:
1) 按y坐标对点进行排序,忽略x坐标:
>>> points = [(1., 1.), (3., 0.),(-1., -1.) , (9., 2.), (-4., 2.)]
>>> points.sort(key=itemgetter(1))
>>> points
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
>>> ^-----------^-----------^-----------^-------------^ ascending y-values
2) 创建具有相同 y 坐标的点组:
>>> pprint([list(g) for k, g in groupby(points, itemgetter(1))], width=40)
[[(-1.0, -1.0)], # y = -1.0
[(3.0, 0.0)], # y = 0.0
[(1.0, 1.0)], # y = 1.0
[(9.0, 2.0), (-4.0, 2.0)]] # y = 2.0
3) 生成具有相同 y 坐标的点的所有排列:
>>> groups = [list(permutations(g)) for k, g in groupby(points, itemgetter(1))]
>>> pprint(groups)
[[((-1.0, -1.0),)], # y = -1.0
[((3.0, 0.0),)], # y = 0.0
[((1.0, 1.0),)], # y = 1.0
[((9.0, 2.0), (-4.0, 2.0)), ((-4.0, 2.0), (9.0, 2.0))]] # y = 2.0
4) 用每个排列组中的一个元素创建所有可能的序列:
>>> for t in product(*groups):
print(t)
(((-1.0, -1.0),), ((3.0, 0.0),), ((1.0, 1.0),), ((9.0, 2.0), (-4.0, 2.0)))
(((-1.0, -1.0),), ((3.0, 0.0),), ((1.0, 1.0),), ((-4.0, 2.0), (9.0, 2.0)))
5) 将每个子序列组合成一个列表:
>>> for t in product(*groups):
list(chain.from_iterable(t))
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (9.0, 2.0), (-4.0, 2.0)]
[(-1.0, -1.0), (3.0, 0.0), (1.0, 1.0), (-4.0, 2.0), (9.0, 2.0)]