ValueError:list.remove(x):python中的x不在列表中问题

ValueError:list.remove(x):python中的x不在列表中问题,python,python-2.7,Python,Python 2.7,有人能帮我解决这个问题吗?我已经做了大量的调试和故障排除,但遇到了麻烦。我不会复制整个脚本,而是复制失败的函数: def deleteOperation(lname1, sKeys, lname2): delMaster = copy.deepcopy(lname2) for k, v in lname1: if k not in sKeys: delMaster.remove((k, v)) return delMaster 以

有人能帮我解决这个问题吗?我已经做了大量的调试和故障排除,但遇到了麻烦。我不会复制整个脚本,而是复制失败的函数:

def deleteOperation(lname1, sKeys, lname2):
    delMaster = copy.deepcopy(lname2)
    for k, v in lname1:
        if k not in sKeys:
            delMaster.remove((k, v))
    return delMaster
以下是参数列表中的值:

lname1 = [(1, 'one'), (3, 'three'), (5, 'five'), (7, 'seven')]
sKeys = [1, 2, 3]
lname2 = [(1, 'one'), (3, 'third'), (5, 'five'), (7, 'seven')]
此函数应该从列表中删除元素
(5,'five')
(7,'seven')
,但当我执行此函数时,出现错误:

ValueError: list.remove(x): x not in list 
实际上,通过使用pyodbc并连接到MS SQL数据库,读取两个表并将这些值保存在lname1和lname2中,我得到了所有的值

有趣的是,如果我使用交互式pythonshell并按照上面打印的方式手动赋值,并且运行与函数完全相同的命令,那么它将不会出错。 我的剧本里有什么线索吗? 感谢您的任何意见


另外,如果我在第4行放置断点,我会看到所有正确的值,但它看起来在列表中。remove()失败了这里有一个简单得多的过程:

>>> lname1=[(1,'one'),(3,'three'),(5,'five'),(7,'seven')]
>>> sKeys=[1,2,3]
>>> filter(lambda (x,y) : x in sKeys, lname1)
[(1, 'one'), (3, 'three')]

创建一个新数组,其中只包含
lname1
中第一个元素在
sKeys

中的项目。问题是
lname1
(k,v)
对的列表,
lname2
(k,w)
的列表,您正在尝试删除
(k,v)
lname2的副本配对。那没有任何意义

对于您碰巧拥有的值,
v
w
对于所有不在
sKeys
中的
k
值都是相同的,因此您可以侥幸逃脱。但是,正如您的示例中的
(3,'third')
所暗示的,以及您在评论中明确指出的那样,这在一般情况下显然是不正确的

因此,如果您试图从
lname2
中删除所有
(k,w)
对,其中一些
(k,v)
lname1
中,但
k
不在
sKeys
中,那么您做得不对;您需要额外搜索才能找到正确的
w

def deleteOperation(lname1, sKeys, lname2):
    delMaster = copy.deepcopy(lname2)
    for k, v in lname1:
        if k not in sKeys:
            for k2, w in lname2:
                if k2 == k:
                    delMaster.remove((k, w))
    return delMaster

或者,先重新组织事物以行走
lname2


或者,最简单的方法是,首先将这些内容转换为dict和set,这样整个操作就变得简单了:

def deleteOperation(lname1, sKeys, lname2):
    for k in lname1:
        if k not in sKeys:
            del lname2[k]
    return lname2

如果您实际上不需要变异
lname2
,而只想从使用
lname1
选择的
lname2
返回值,则可以简化此操作。那就只是:

def deleteOperation(lname1, sKeys, lname2):
    d2 = dict(lname2)
    return [(k, d2[k]) for k, v in lname1 if k in sKeys]
再说一次,如果您首先使用正确的数据结构,情况会更简单:

def deleteOperation(lname1, sKeys, lname2):
    return {k: lname2[k] for k in sKeys & lname1.keys()}

帮你自己一个忙,用一张理解清单。这样,您就不必担心在Python3中,
filter
不会返回
列表。这在Python2或Python3中同样有效

>>> lname1 = [(1, 'one'), (3, 'three'), (5, 'five'), (7, 'seven')]
>>> sKeys = [1, 2, 3]
>>> [(x, y) for x, y in lname1 if x in sKeys]
[(1, 'one'), (3, 'three')]

为了更好地诊断您的异常,您可以这样处理异常

def deleteOperation(lname1, sKeys, lname2):
    delMaster = copy.deepcopy(lname2)
    for k, v in lname1:
        if k not in sKeys:
            try:
                delMaster.remove((k, v))
            except ValueError:
                print("{} not found in {}".format((k,v), delMaster))
    return delMaster

复制列表然后从中删除是一种不同寻常的方法。通常,将确实需要的项复制到新的数据结构会更高效、更安全。你这样做有什么特别的原因吗?

我刚刚运行了你的代码,它会像预期的那样返回
[(1,'one'),(3,'third')]
。lname2和lname1是否可能有不同的内容?在Python中更常见的做法是只构建一个只包含所需键的新副本,而不是构建一个完整的深度副本,然后删除不需要的密钥。你这样做有什么原因吗?请张贴你的实际代码。另外,我认为只返回一个新的dictionary
{key:lname2[key]for key in lname1}
会容易得多。lname1和lname2确实有不同的内容,即(3,'tree')和(3,'third'),应该是这样的,因为在以前的操作中,我用新的值'third'更新了lname1,现在在我的程序中工作得很好。请你解释一下lambda在你的案例中是如何工作的好吗。看来我已经准备好了。只是想了解一下flow@susja:lambda只定义了一个函数
lambda(x,y):sKeys中的x定义了与
def fn(x,y):在sKeys中返回x完全相同的函数。虽然实际上,这里根本不需要函数;您可以只使用理解,如
[x代表x,如果x代表sKeys,则在lname1中为y]
。作为补充说明,此语法已被弃用(并且在3.x中不起作用);您需要在整个lambda中使用paren,而不应该在参数列表中使用paren。@abarnert,在Python3中,您还需要使用
list(filter(…)
谢谢大家。我只是对如此多的积极回应感到惊讶。阿巴内特-非常感谢。您的回答很好,但我更喜欢使用使用lambda的更简单的解决方案。谢谢你。@susja:如果你一开始就使用了dict和set,而且你不需要改变东西,Blender评论中的dict理解要比这两个答案简单得多。我认为这并不能回答问题。请注意,OP的原始代码从
lname2
返回键和值,而不是
lname1
。特别是,您返回的是
(3,'三')
而不是
(3,'三')
@abarnert,我认为整个问题目前无法回答。我们真的不知道当
k
匹配而
v
不匹配时会发生什么。susja甚至还没有考虑过这个案子。我把这个放在这里是因为它比使用
filter
的答案要好,我试图在我的答案中解释这一点,起初OP同意我对他的意思的猜测…但后来他接受了一个不同的答案,认为
lname2
实际上应该被完全忽略,这意味着…是的,我不认为他真的知道他想要什么。