1

我有以下列表_A:

['0', '1', '2', '3', '4', '5', '6', '7']

还有另一个list_B:

['2','6','7']

我想检查一下:对于“list_A”中的每个元素,如果它是“list_B”中的元素之一

所以:

for 0 <-> are you one of these? ['2','6','7']
for 1 <-> are you one of these? ['2','6','7']
for 2 <-> are you one of these? ['2','6','7']

最后,我想提出一个“list_C”,它在元素计数方面与“list_A”相同,但更像是一个看起来像这样的地图:

['-1', '-1', '2', '-1', '-1', '-1', '6', '7']

即:每个非匹配元素为“-1”,每个匹配元素为“self”。显然,我正在为每个周期嵌套 2 个,并且它有效:

myStateMap = []

for a in list_A:
    elementString = -1
    for b in list_B:
        if a == b:
            # Update the elementString in case of a match
            elementString = a
            print "\tMatch"
        else:
            pass
            print "\tNO Match!"
    # Store the elementString
    myStateMap.append(elementString)

问题是:您将如何优化它?您将如何使其更短、更高效?

4

4 回答 4

4

您可以使用列表理解

>>> [('-1' if item not in list_B else item) for item in list_A]
['-1', '-1', '2', '-1', '-1', '-1', '6', '7']
于 2013-11-07T13:55:08.563 回答
4

使用带有条件表达式的列表推导:

[i if i in list_B else '-1' for i in list_A]

演示:

>>> list_A = ['0', '1', '2', '3', '4', '5', '6', '7']
>>> list_B = ['2','6','7']
>>> [i if i in list_B else '-1' for i in list_A]
['-1', '-1', '2', '-1', '-1', '-1', '6', '7']

如果list_B很大,则应改为设置:

set_B = set(list_B)

加快会员测试。in在列表上具有线性成本(需要扫描的元素越多,花费的时间越长),而针对集合的相同测试需要恒定成本(与集合中值的数量无关)。

对于您的具体示例,使用集合已经更快:

>>> timeit.timeit("[i if i in list_B else '-1' for i in list_A]", "from __main__ import list_A, list_B")
1.8152308464050293
>>> timeit.timeit("set_B = set(list_B); [i if i in set_B else '-1' for i in list_A]", "from __main__ import list_A, list_B")
1.6512861251831055

但是如果list_A比率list_B不同并且尺寸很小:

>>> list_A = ['0', '1', '2', '3']
>>> list_B = ['2','6','8','10']
>>> timeit.timeit("[i if i in list_B else '-1' for i in list_A]", "from __main__ import list_A, list_B")
0.8118391036987305
>>> timeit.timeit("set_B = set(list_B); [i if i in set_B else '-1' for i in list_A]", "from __main__ import list_A, list_B")
0.9360401630401611

也就是说,在一般情况下,使用集合是值得的。

于 2013-11-07T13:55:15.880 回答
0

最快的优化方法是使用if a in list_B:而不是你的内部循环。所以新代码看起来像:

for a in list_A:
    if a in list_B:
        myStateMap.append(a)
        print '\tMatch'
    else:
        print '\tNO Match!'
        myStateMap.append(-1)
于 2013-11-07T14:17:26.300 回答
0

这是另一个与其他列表略有不同的简短列表理解示例:

a=[1,2,3,4,5,6,7]
b=[2,5,7]
c=[x * (x in b) for x in a]

这给了c = [0, 2, 0, 0, 5, 6, 7]. 如果您的列表元素实际上是字符串,就像它们看起来那样,那么您要么得到空字符串,要么得到''原始字符串。这利用了将布尔值 ( x in b)隐式转换为将其乘以原始值0或之前的隐式转换(在字符串的情况下,这是“重复连接”)。1

于 2013-11-07T16:06:35.633 回答