2013-04-16 37 views
0

Как стартер python, пытаясь получить помощь от умных людей, столкнувшись с проблемой. И вот сейчас:Python - как сравнить все элементы в списке

Мне нужно сравнить предметы (предметы сцены Qt) из одного списка между собой и сделать отдельные группы предметов, которые сталкиваются друг с другом.

Пожалуйста, помогите мне с кодом:

class MainWin(QMainWindow): 
    def __init__(self): 
     super(MainWin, self).__init__() 
     self.Win() 
     self.L = self.buildAllWalls() 
     items = self.scene.items() 
     allGroups = groupItemsFromList(None, items) 
     self.paintGroups(allGroups) 
     print len(allGroups) 

    def paintGroups(self, groups): 
     for g in groups : 
      color = QColor(0, 0, 0) 
      # RANDOM COLOR 
      namcol = "#%s" % "".join([hex(randrange(0, 255))[2:] for i in range(3)]) 
      color.setNamedColor(namcol) 
      while color.isValid() == False : # ERROR CHECK 
       namcol = "#%s" % "".join([hex(randrange(0, 255))[2:] for i in range(3)]) 
       color.setNamedColor(namcol) 
      pen = QPen(color, 14, Qt.SolidLine) 
      for w in g : 
       w.setPen(pen) 

    def Win(self): 
     self.scene = QGraphicsScene() 
     self.sView = QGraphicsView(self.scene) 
     self.sView.setRenderHint(QPainter.Antialiasing) 
     self.sView.setAlignment(Qt.AlignLeft | Qt.AlignTop) 

     self.setCentralWidget(self.sView) 
     self.setGeometry(20, 380, 400, 300) 
     self.show() 

    def buildAllWalls(self): 
     data = self.wallCoordinates() 
     for p in range(len(data)) : 
      ptA = QPointF(data[p][0], data[p][1]) 
      ptB = QPointF(data[p][2], data[p][3]) 
      self.wall(ptA, ptB) 

    def wall(self, ptA, ptB): 
     pen = QPen(QColor(100, 100, 100), 14, Qt.SolidLine) 
     currL = self.scene.addLine(QLineF(ptA.x(), ptA.y(), ptB.x(), ptB.y())) 
     currL.setPen(pen) 
     return currL 

    #[50,75,325,75], 
    def wallCoordinates(self): 
     data = [[50,100,150,100],[175,200,125,200],[175,275,125,275],[175,275,175,200], 
      [150,150,150,100],[175,100,225,100],[250,100,325,100],[350,125,175,125], 
      [50,125,125,125],[125,175,125,125],[150,150,175,150],[175,150,175,200], 
      [50,150,100,150],[100,150,100,200],[100,200,125,200],[50,175,75,175], 
      [75,225,75,175],[75,225,125,225],[125,275,125,225]] 
     return data 

def main(): 

    app = QApplication(sys.argv) 
    ex = MainWin() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 
+0

В чем проблема и какой выход нужен? –

+0

Как только объяснялось, мне нужно сравнить элементы списка элементов между собой, чтобы составить список групп, которые сталкиваются. – Alex

+0

Обратите внимание, что для boolean и используйте оператор 'and', а не' & '. – mgilson

ответ

1

Вот как я это пишу:

def groupItemsFromList(self, itemList): 
    tmp = itemList[:] 
    allGroups = [] 
    while tmp: 
     it = tmp.pop(0) 
     currentGroup = [it] 
     # loop from back to front so we can remove items safely 
     for i in range(len(tmp)-1, -1, -1): 
      if it.collidesWithItem(tmp[i]): 
       currentGroup.append(tmp.pop(i)) 
     allGroups.append(currentGroup) 
    return allGroups 

Например:

class Test(object): 
    def __init__(self, key): 
     self.key = key 
    def collidesWithItem(self, other): 
     return isinstance(other, self.__class__) and self.key == other.key 
    def __repr__(self): 
     return '{0}({1})'.format(self.__class__.__name__, self.key) 

example = [Test(1), Test(2), Test(1), Test(1), Test(3), Test(2), Test(3), Test(4)] 
print groupItemsFromList(None, example) 

Выход:

[[Test(1), Test(1), Test(1)], [Test(2), Test(2)], [Test(3), Test(3)], [Test(4)]] 

Это делает предположение, что все предметы, которые сталкиваются с предметом, также будут сталкиваться друг с другом.

редактировать: Похоже, предположение не действует, попробуйте следующее (непроверенные):

def groupItemsFromList(self, itemList): 
    tmp = itemList[:] 
    allGroups = [] 
    while tmp: 
     it = tmp.pop(0) 
     currentGroup = [it] 
     i = len(tmp) - 1 
     while i >= 0: 
      if any(x.collidesWithItem(tmp[i]) for x in currentGroup): 
       currentGroup.append(tmp.pop(i)) 
       i = len(tmp) - 1 
      else: 
       i -= 1 
     allGroups.append(currentGroup) 
    return allGroups 
+0

+1, и нужно проверить его. Я хочу проверить Истину всем вам, ребята, здесь, чтобы не торопиться, чтобы объяснить мне. Весьма признателен. – Alex

+0

Сегодня я проверил ваш код. Пока ваш тест проходит, попробуйте реализовать его и заметите, что подгруппы имеют только 2 элемента, игнорируя другие. Пожалуйста, повторите попытку. Я могу опубликовать код. – Alex

+1

@Alex Я не уверен, что понимаю эту проблему. Если возможно, попробуйте предоставить минимальный пример, который показывает проблему. Например, если вы можете придумать пример типа «Для списка' [A, B, C, D, E] ', где' A' сталкивается с 'B' и' C', сталкивается с ..., результатом является '[[A, B], [C, ...]]', когда это должно быть '[[A, B], ...]'. –

1

Похоже, что вы могли бы сделать это:

def groupItemsFromList(self, itemList): 
    """ 
    Make a list of lists, where each list is composed of the 
    items (excepting itself, of course) that an item collides with. 
    """ 
    return [ 
     [item for item in itemList[:i] + itemList[i:] if item.collidesWithItem(x)] 
     for i, x in enumerate(itemList) 
    ] 

itemList[:i] + itemList[i:] является Идиома python для «Я хочу все элементы исходного списка, кроме i-го элемента».


Позже: Я вижу. Вы хотите что-то еще вот так:

def groupItemsFromList(self, itemList): 
    def collision_indexes(i, target): 
     return [i] + [j for j, item in enumerate(itemList[i + 1:], start=i + 1) if item.collidesWithItem(target)] 

    processed = set() 
    results = [] 
    for i, target in enumerate(itemList): 
     if i not in processed: 
      indexes = collision_indexes(i, target) 
      processed.update(indexes) 
      results.append([itemList[j] for j in indexes]) 
    return results 

Единственное преимущество здесь в том, что это код без побочных эффектов. Не существует мутации исходных данных, а только функции, применяемые к данным и изменениям, внесенным в новые, временные структуры данных.

+0

+1 ... Я собираюсь поставить его на тест. Должен признаться, ваш всеобъемлющий код потряс меня! Вау! – Alex

+0

Он почти выполняет свою работу, на самом деле, это переусердствует. Копирует несколько элементов в несколько раз больше. Вы можете улучшить его, пожалуйста? В любом случае спасибо огромное. – Alex

+1

'Копирует несколько элементов в несколько раз больше. Пожалуйста, дайте пример с данными и желаемым выходом. – hughdbrown

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