我一直在搜索,我看到的大多数错误都是人们试图迭代列表并同时修改它的时候。在我的情况下,我试图获取一个列表,并从该列表中删除第二个列表中的项目。
import pymysql
schemaOnly = ["table1", "table2", "table6", "table9"]
db = pymysql.connect(my connection stuff)
tables = db.cursor()
tables.execute("SHOW TABLES")
tablesTuple = tables.fetchall()
tablesList = []
# I do this because there is no way to remove items from a tuple
# which is what I get back from tables.fetchall
for item in tablesTuple:
tablesList.append(item)
for schemaTable in schemaOnly:
tablesList.remove(schemaTable)
当我在代码中放入各种打印语句时,一切看起来都很合适,并且它会起作用。但当它达到实际的tablesList.remove(schemaTable)
时,我会感到害怕ValueError: list.remove(x): x not in list
。
如果有更好的方法可以做到这一点,我愿意接受各种想法。对我来说,遍历列表并删除项目似乎是合乎逻辑的。
提前致谢!
**编辑**
评论中的每个人和第一个答案都是正确的。失败的原因是因为从元组到列表的转换正在创建格式非常糟糕的列表。因此,在尝试删除下一循环中的项目时,没有任何内容匹配。这个问题的解决方案是从每个元组中取出第一个项目并将它们放入如下列表:tablesList = [x[0] for x in tablesTuple]
。一旦我这样做,第二个循环工作,表名被正确删除。
感谢您指出我正确的方向!
答案 0 :(得分:0)
我假设fetchall
返回元组,每个匹配的数据库行一个。
现在问题是tablesList
中的元素是元组,而schemaTable
包含字符串。 Python并不认为这些是平等的。
因此,当您尝试使用remove
中的字符串在tablesList
上调用schemaTable
时,Python无法找到任何此类值。
您需要检查tablesList
中的值并找到将它们转换为字符串的方法。我怀疑它只是从元组中取出第一个元素,但我手头没有mySQL数据库所以我无法测试它。
答案 1 :(得分:0)
关于你的问题,如果有更好的方法:是的。
您可以只追加所需的项目,而不是将项目添加到列表中,然后将其删除。例如:
for item in tablesTuple:
if item not in schemaOnly:
tablesList.append(item)
此外,schemaOnly可以写成一个集合,以提高从O(n)到O(1)的搜索复杂度:
schemaOnly = {"table1", "table2", "table6", "table9"}
这只适用于大型列表,但根据我的经验,它在语义上很有用。
最后,你可以用一个列表理解来编写整个事物:
tablesList = [item for item in tablesTuple if item not in schemaOnly]
如果你不需要重复(或者如果首先没有重复),你也可以这样做:
tablesSet = set(tablesTuple) - schemaOnly
这也是所有这些变化中最好的大O复杂性。