【问题标题】:Python list of objects, get all 'orientations' of attributesPython 对象列表,获取属性的所有“方向”
【发布时间】:2015-05-01 14:01:07
【问题描述】:

我有一个对象列表(矩形)。每个对象有 2 个属性(高度和宽度)。我想得到这个列表的所有“方向”(不知道如何准确地调用它),所以所有 2^n(对于 n 个矩形的列表)方向,其中矩形的高度和宽度(可能)交换.对于 3 个对象的列表,它看起来像这样(顺序并不重要):

[R1(w, h), R2(w2, h2), R3(w3, h3)]
[R1(w, h), R2(w2, h2), R3(h3, w3)]
[R1(w, h), R2(h2, w2), R3(w3, h3)]
[R1(w, h), R2(h2, w2), R3(h3, w3)]
[R1(h, w), R2(w2, h2), R3(w3, h3)]
[R1(h, w), R2(w2, h2), R3(h3, w3)]
[R1(h, w), R2(h2, w2), R3(w3, h3)]
[R1(h, w), R2(h2, w2), R3(h3, w3)]

我的矩形类如下所示:

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def place(self):
        """Method to place tile in a larger grid"""

    def remove(self):
        """Method to remove tile from larger grid"""

有没有简单的方法可以做到这一点?

【问题讨论】:

  • 我部分理解了您的问题,但数据不足以为您所谈论的问题奠定坚实的基础。能说清楚点吗?
  • 我有一个对象列表(矩形)。这些矩形可以旋转(交换高度和宽度)。对于 8 个矩形的列表,这会导致 8 个矩形有 2^8 个不同的方向。有没有一种简单的方法来生成这 2^8 个不同的方向?希望这能让它更清楚一点..
  • [[R1(w, h), R2(w, h), R3(w, h)] for _ in range(2**len([R1(w, h), R2(w, h), R3(w, h)]))] 应该可以工作。您可以将该列表存储在变量中并使用它。
  • 这听起来像是itertools 的工作,特别是product 方法。您还需要一个可以接收矩形并返回转置(旋转)矩形的函数或方法。但这应该很容易做到。您可以在问题中添加矩形类的定义吗?如果您的实际课程很复杂,只需发布​​一个精简版,以便我们了解如何访问宽度和高度属性。
  • 这是一个好的开始:product([orientation1,orientation2], repeat=len(objects))

标签: python list object attributes swap


【解决方案1】:

准备工作:

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def flipped(self):
        return Rectangle(self.width, self.height)

    def __repr__(self):
        return 'Rectangle({}, {})'.format(self.height, self.width)

rectangles = [Rectangle(1, 10), Rectangle(2, 20), Rectangle(3, 30)]

解决方案:

from itertools import product
for orientation in product(*zip(rectangles, map(Rectangle.flipped, rectangles))):
    print(orientation)

输出:

(Rectangle(1, 10), Rectangle(2, 20), Rectangle(3, 30))
(Rectangle(1, 10), Rectangle(2, 20), Rectangle(30, 3))
(Rectangle(1, 10), Rectangle(20, 2), Rectangle(3, 30))
(Rectangle(1, 10), Rectangle(20, 2), Rectangle(30, 3))
(Rectangle(10, 1), Rectangle(2, 20), Rectangle(3, 30))
(Rectangle(10, 1), Rectangle(2, 20), Rectangle(30, 3))
(Rectangle(10, 1), Rectangle(20, 2), Rectangle(3, 30))
(Rectangle(10, 1), Rectangle(20, 2), Rectangle(30, 3))

【讨论】:

  • 好吧,我确实说“可能有一些更高级的 itertools 技巧”。 :) map 的使用很好;我真的需要更多地练习使用它......
  • 这不是一个技巧,但它正是应该如何使用产品。 你的是个把戏:-)
  • 是的,好的。我想我应该承认,我对正确使用 itertools 并不熟悉......
  • 顺便说一句,请随时访问SO Python Chat room。
  • @PM2Ring 谢谢,我不知道聊天。我去看看。
【解决方案2】:

这里有一些 Python 代码可以满足您的需求。如果您修复了show() 函数中的打印语句,它应该很容易在 Python 3 上运行。

#!/usr/bin/env python

''' Build a list of lists containing all combinations of orientations
    (i.e. landscape & portrait) for a list of Rectangle objects

    From http://stackoverflow.com/q/29988288/4014959

    Written by PM 2Ring 2015.05.02
'''

from itertools import product

#A simple rectangle class
class Rectangle(object):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def __repr__(self):
        return 'Rectangle({0}, {1})'.format(self.width, self.height)

    def transpose(self):
        return Rectangle(self.height, self.width)

#Helper function to print sequences
def show(seq):
    for item in seq:
        print item
    print

#A list of rectangle objects
rects_orig = [
    Rectangle(1, 2), 
    Rectangle(3, 4), 
    Rectangle(5, 6),
]
show(rects_orig)

#The transposed versions of those rectangles
rects_rot = [rect.transpose() for rect in rects_orig]
show(rects_rot)

#Join both lists into a list of tuples
rects_both = zip(rects_orig, rects_rot) 
show(rects_both)

#Build the combinations.
combos = [] 
for align in product([0, 1], repeat=len(rects_both)):
   combos.append([rect_pair[a] for a, rect_pair in zip(align, rects_both)])

show(combos)

输出

Rectangle(1, 2)
Rectangle(3, 4)
Rectangle(5, 6)

Rectangle(2, 1)
Rectangle(4, 3)
Rectangle(6, 5)

(Rectangle(1, 2), Rectangle(2, 1))
(Rectangle(3, 4), Rectangle(4, 3))
(Rectangle(5, 6), Rectangle(6, 5))

[Rectangle(1, 2), Rectangle(3, 4), Rectangle(5, 6)]
[Rectangle(1, 2), Rectangle(3, 4), Rectangle(6, 5)]
[Rectangle(1, 2), Rectangle(4, 3), Rectangle(5, 6)]
[Rectangle(1, 2), Rectangle(4, 3), Rectangle(6, 5)]
[Rectangle(2, 1), Rectangle(3, 4), Rectangle(5, 6)]
[Rectangle(2, 1), Rectangle(3, 4), Rectangle(6, 5)]
[Rectangle(2, 1), Rectangle(4, 3), Rectangle(5, 6)]
[Rectangle(2, 1), Rectangle(4, 3), Rectangle(6, 5)]

【讨论】:

  • 谢谢!这正是我想要的:)
  • 我的荣幸!该代码可以压缩成更少的行,但我认为它在当前状态下更具可读性。此外,可能有一些更高级的 itertools 技巧可以用更少的代码实现所需的结果,但我更喜欢直接的代码而不是我在 6 个月内无法弄清楚的代码。 :)
  • 如果您绕了这么复杂的[0,1] 弯路,这并不简单。请参阅我对product 的实际直接使用的回答。
  • @StefanPochmann:好电话。我应该知道最好不要在凌晨 1 点编码。 :)
  • @Koen:你应该“接受”Stefan 的回答。它比我的好,所以他应该得到(一些:))积分。
猜你喜欢
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 2019-01-12
  • 2011-10-16
  • 2019-09-05
  • 1970-01-01
  • 2011-09-20
相关资源
最近更新 更多