0

作为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()
4

2 回答 2

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
于 2013-04-16T17:32:26.093 回答
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:]是“我想要原始列表中除第 i 个项目之外的所有元素”的 python 习语。


后来:我明白了。你想要更像这样的东西:

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

这里唯一的优点是这是无副作用的代码。原始数据没有变化,只有应用于数据的函数和对新的临时数据结构所做的更改。

于 2013-04-16T17:34:03.997 回答