2015-05-01 2 views
4

У меня есть список объектов (прямоугольники). Каждый объект имеет 2 атрибута (высота и ширина). Я хотел бы получить все «ориентации» (не уверен, как назвать это точно) этого списка, поэтому все 2^n (для списка n прямоугольников) ориентации, в которых высота и ширина прямоугольников (возможно) меняются местами , Для получения списка 3 объектов это будет выглядеть следующим образом (порядок не важен):Python список объектов, получить все «ориентации» атрибутов

[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""" 

Есть простой способ сделать это?

+0

Я частично понял ваш вопрос, но данные недостаточны, чтобы получить прочную основу проблемы, о которой вы говорите. Можете ли вы быть более ясными? – ZdaR

+0

У меня есть список объектов (прямоугольники). Эти прямоугольники можно поворачивать (так что высота и ширина меняются местами). Для списка из 8 прямоугольников это приводит к 2^8 различным ориентациям 8 прямоугольников. Есть ли простой способ генерировать эти 2^8 разных ориентаций? Надеемся, что это станет более понятным. – Koen

+0

'[[R1 (w, h), R2 (w, h), R3 (w, h)] для _ в диапазоне (2 ** len ([R1 (w, h), R2 (w, h), R3 (w, h)]))] 'должен работать. Вы можете сохранить этот список в переменной и использовать его. –

ответ

3

Приготовление:

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)) 
+0

Ну, я сказал, «может быть какой-то причудливый трюк itertools». :) Это использование «карты» приятно; Мне действительно нужно больше практики, используя его ... –

+0

Это не трюк, однако, это точно, как предполагается использовать продукт. * Твой * был трюк :-) –

+0

Да, хорошо. Полагаю, я должен признать, что я не так хорошо знаком с правильным использованием itertools, как и должен быть ... –

3

Вот код Python, который делает то, что вы хотите. Он должен легко запускаться на Python 3, если вы исправите оператор печати в функции show().

#!/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)] 
+0

Спасибо! Это точно то, что я искал :) – Koen

+0

Мое удовольствие! Этот код _could_ будет сокращен до меньшего количества строк, но я думаю, что это более читаемо в текущем состоянии. Кроме того, может быть какой-то притворный трюк itertools для достижения желаемого результата с меньшим количеством кода, но я предпочитаю прямолинейный код для кода, который я не смогу найти через 6 месяцев. :) –

+0

Это не прямолинейно, если вы берете этот сложный '[0,1]' обход. См. Мой ответ на прямое использование 'product'. –

Смежные вопросы