[英]Python nested for loop: what am I doing wrong?
I am working with data pulled from a spreadsheet-like file. 我正在处理从类似电子表格的文件中提取的数据。 I am trying to find, for each "ligand", the item with the lowest corresponding "energy".
我试图为每个“配体”找到对应的“能量”最低的项目。 To do this I'm trying to make a list of all the ligands I find in the file, and compare them to one another, using the index value to find the energy of each ligand, keeping the one with the lowest energy.
为此,我尝试列出我在文件中找到的所有配体的列表,并将它们相互比较,使用索引值找到每个配体的能量,并保持能量最低。 However, the following loop is not working out for me.
但是,以下循环对我而言不起作用。 The program won't finish, it just keeps running until I cancel it manually.
该程序不会完成,它会一直运行直到我手动取消它。 I'm assuming this is due to an error in the structure of my loop.
我假设这是由于循环结构中的错误引起的。
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))
As you can see, I've created a separate ligandList containing the ligands, and am using the current index of that list to access the energy values in the lineList. 如您所见,我创建了一个包含配体的单独的配体列表,并且正在使用该列表的当前索引来访问lineList中的能量值。
Does anyone know why this isn't working? 有人知道为什么这行不通吗?
It is a bit hard to answer without some actual data to play with, but I hope this works, or at least leads you into the right direction: 没有一些实际数据可玩,这很难回答,但是我希望这能奏效,或者至少可以引导您朝正确的方向前进:
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]
You look like you're trying to find the element in ligandList
with the smallest value in index 42. Let's just do that.... 您似乎正在尝试在索引值为42的配体列表中
ligandList
具有最小值的元素。
min(ligandList, key=lambda x: float(x[42]))
If these "Ligands" are something you use regularly, STRONGLY consider writing a class wrapper for them, something like: 如果这些“配体”是您经常使用的东西,则强烈考虑为它们编写一个类包装器,例如:
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...
In which case you can simply create a list of the Ligands: 在这种情况下,您只需创建一个配体列表:
ligands = [Ligand(ligand) for ligand in ligandList]
and return the object with the smallest energy: 并返回能量最小的对象:
lil_ligand = min(ligands, key=lambda ligand: ligand.energy)
As a huge aside, PEP 8 encourages the use of the lowercase
naming convention for variables, rather than mixedCase
as many languages use. 除了一个很大的方面, PEP 8鼓励对变量使用
lowercase
命名约定,而不是像许多语言所使用的mixedCase
。
That's a really inefficient way of doing things. 这是一种非常低效的处理方式。 Lots of
index
calls. 很多
index
调用。 It might just feel infinite because it's slow. 它可能会感觉很无限,因为它很慢。
Zip your related things together: 将您的相关内容压缩在一起:
l = zip(ligandList, lineList)
Sort them by “ligand” and “energy”: 按“配体”和“能量”对它们进行排序:
l = sorted(l, key=lambda t: (t[0], t[1][42]))
Grab the first (lowest) “energy” for each: 抓住每个(最低)的“能量”:
l = ((lig, lin[1].next()[1]) for lig, lin in itertools.groupby(l, key=lambda t: t[0]))
Yay. 好极了。
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]
))
It would probably look more flattering if you made lineList
contain classes of some kind. 如果使
lineList
包含某种类,它看起来可能会更讨人喜欢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.