Python嵌套for循环:我做错了什么?

时间:2014-01-21 19:08:41

标签: python loops

我正在处理从类似电子表格的文件中提取的数据。我试图为每个“配体”找到具有最低相应“能量”的项目。为此,我试图列出我在文件中找到的所有配体,并将它们相互比较,使用指数值找到每个配体的能量,保持能量最低的配体。但是,以下循环对我来说不起作用。程序无法完成,它会一直运行,直到我手动取消它。我假设这是由于我的循环结构错误。

for item in ligandList:
    for i in ligandList:
        if ligandList.index(item) != ligandList.index(i):
            if ( item == i ) :
                if float(lineList[ligandList.index(i)][42]) < float(lineList[ligandList.index(item)][42]):
                    lineList.remove(ligandList.index(item))
                else:
                    lineList.remove(ligandList.index(i))

如您所见,我创建了一个包含配体的独立配体列表,并使用该列表的当前索引来访问lineList中的能量值。

有谁知道为什么这不起作用?

3 个答案:

答案 0 :(得分:2)

如果没有一些实际数据可以回答有点难以回答,但我希望这有效,或至少引导您走向正确的方向:

for idx1, item1 in enumerate(ligandList):
    for idx2, item2 in enumerate(ligandList):
        if idx1 == idx2: continue
        if item1 != item2: continue
        if float(lineList[idx1][42]) < float(lineList[idx2][42]):
            del lineList [idx1]
        else:
            del lineList [idx2]

答案 1 :(得分:1)

你看起来好像在尝试在ligandList中找到索引为42的最小值的元素。让我们这样做....

min(ligandList, key=lambda x: float(x[42]))

如果这些“Ligands”是您经常使用的东西,那么强烈考虑为它们编写类包装器,例如:

class Ligand(object):
    def __init__(self,lst):
        self.attr_name = lst[index_of_attr] # for each attribute
        ... # for each attribute
        ... # etc etc
        self.energy = lst[42]
    def __str__(self):
        """This method defines what the class looks like if you call str() on
it, e.g. a call to print(Ligand) will show this function's return value."""
        return "A Ligand with energy {}".format(self.energy) # or w/e
    def transmogfiscate(self,other):
        pass # replace this with whatever Ligands do, if they do things...

在这种情况下,您只需创建一个配体列表:

ligands = [Ligand(ligand) for ligand in ligandList]

并返回能量最小的物体:

lil_ligand = min(ligands, key=lambda ligand: ligand.energy)

另外,PEP 8鼓励对变量使用lowercase命名约定,而不是像许多语言一样使用mixedCase

答案 2 :(得分:1)

这是一种非常低效的做事方式。很多index次来电。它可能只是感觉无限,因为它很慢。

将您的相关内容拼凑在一起:

l = zip(ligandList, lineList)

按“配体”和“能量”对它们进行排序:

l = sorted(l, key=lambda t: (t[0], t[1][42]))

抓住每个人的第一个(最低)“能量”:

l = ((lig, lin[1].next()[1]) for lig, lin in itertools.groupby(l, key=lambda t: t[0]))

耶。

result = ((lig, lin[1].next()[1]) for lig, lin in itertools.groupby(
    sorted(zip(ligandList, lineList), key=lambda t: (t[0], t[1][42])),
    lambda t: t[0]
))

如果你让lineList包含某种类,那么看起来会更讨人喜欢。

Demo