python - 用两个不同列表中的值替换列表的布尔值

时间:2017-02-03 16:20:06

标签: python list replace boolean

我有一个列表,其中包含布尔值,如

lyst = [True,True,False,True,False]

和两个不同的列表,例如:

car = ['BMW','VW','Volvo']
a = ['b','c']

我只想将car中的值替换为True,将a中的值替换为False。 或者使用lyst中的序列和car以及a中的值创建新列表。 结果应该是

[BMW,VW,b,Volvo,c].

到目前为止我的代码:

for elem1,elem2,elem3 in zip(lyst,car,a):
    subelem2=elem2
    subelem3=elem3
    if elem1 != True:
        result_list.append(subelem2)
    else: 
        result_list.append(subelem3)

但这会创建一个长于5的列表匹配。

我该怎么做?

6 个答案:

答案 0 :(得分:6)

car = iter(car)
a = iter(a)
[next(car) if item else next(a) for item in lyst]

好的,我无法自拔:

car = iter(car)
a = iter(a)
[(flag and next(car)) or next(a) for flag in lyst]

这使用了一些布尔表达式功能:

  • 如果第一个操作数为False,则布尔值and表达式不会计算第二个操作数
  • 如果两个操作数都计算为True,则布尔and表达式将返回第二个操作数(实际对象)
  • 布尔值or表达式将返回第一个计算结果为True的对象

如果cara中的任何项目评估为False,则可能存在问题。这也不像第一个解决方案中的三元一样可读。

但这很有趣。

我想我会在再次查看之后添加它,我可能不应该重新分配原始列表名称 - 我应该为迭代器名称选择不同的东西。一旦耗尽,迭代器就不能重置,并且由于列表名称被重新分配,原始列表信息将丢失。

答案 1 :(得分:6)

假设True中的Falselyst条目数正确,您可以通过创建其他两个列表的迭代器来有效地执行此操作。这比列表前面的pop更有效。

lyst = [True, True, False, True, False]
car = ['BMW', 'VW', 'Volvo']
a = ['b', 'c']
selector = [iter(a), iter(car)]
result = [next(selector[b]) for b in lyst]
print(result)

<强>输出

['BMW', 'VW', 'b', 'Volvo', 'c']

selector[b]构造有效,因为False的数值为0,True的数值为1,因此我们可以使用lyst的布尔值索引到selector列表。

计时

我决定编写一个timeit脚本来比较此处发布的各种算法的速度,以及来自the dupe target question的vaultah代码。

为了测试这些算法,我将它们全部付诸实践。要获得准确的计时数据timeit多次运行该函数。使用.pop的算法会使用它们弹出的列表,因此我必须向这些函数添加代码以创建这些列表的副本。显然,复制过程会降低这些功能的速度,在某些应用程序中,输入数据列表可能会被破坏并不重要,但我觉得需要包含复制时间才能比较这些函数的速度以便更广泛地使用。

timeit测量挂钟时间而不是CPU时间,因此时间将受到系统上运行的其他进程的影响。因此,在运行timeit代码时,最好尽可能减少系统负载。理想情况下,您应该关闭网络访问,或者至少在测试运行时避免使用浏览器。绝对不要听音乐或看视频。 :)

下面的代码在Python 2.6+以及Python 3上运行。我在Python 2.6.6和Python 3.6.0上进行了测试。

#!/usr/bin/env python3

''' Merge two lists according to a list of booleans

    Given data lists `alist` and `blist`, iterate over boolean list `chooser`.
    If the current item in `chooser` is False, append the next item from `alist`
    to the output list.
    If the current item in `chooser` is True, append the next item from `blist`
    to the output list.

    See https://stackoverflow.com/q/42028606/4014959

    Speed tests of implementations by various authors
    Timing code written by PM 2Ring 2016.12.28
'''

# Python 2 / 3 compatible

from __future__ import print_function, division
from timeit import Timer
from random import seed, shuffle

seed(1234)

# The functions to test

def merge_wwii_ifelse(alist, blist, chooser):
    alist = iter(alist)
    blist = iter(blist)
    return [next(blist) if item else next(alist) for item in chooser]

def merge_wwii_andor(alist, blist, chooser):
    alist = iter(alist)
    blist = iter(blist)
    return [(flag and next(blist)) or next(alist) for flag in chooser]

def merge_PM2R_it(alist, blist, chooser):
    selector = [iter(alist), iter(blist)]
    return [next(selector[b]) for b in chooser]

def merge_PM2R_pop(alist, blist, chooser):
    alist = list(alist)
    blist = list(blist)
    return [blist.pop() if item else alist.pop() for item in reversed(chooser)][::-1]

def merge_AlexL(alist, blist, chooser):
    alist = list(alist)
    blist = list(blist)
    return [blist.pop(0) if item else alist.pop(0) for item in chooser]

def merge_Laurent(alist, blist, chooser):
    selector = {True: iter(blist), False: iter(alist)}
    return [next(selector[flag]) for flag in chooser]

def merge_Shihab(alist, blist, chooser):
    i = j = 0
    ans = []
    for v in chooser:
        if v:
            ans.append(blist[i])
            i += 1
        else:
            ans.append(alist[j])
            j += 1
    return ans

def merge_EvKounis(alist, blist, chooser):
    mapping = {True: list(blist), False: list(alist)}
    return [mapping[c].pop(0) for c in chooser]

def merge_vaultah(alist, blist, chooser):
    i1 = iter(alist)
    i2 = iter(blist)
    return [next(i2 if x else i1) for x in chooser]

funcs = (
    merge_wwii_ifelse,
    merge_wwii_andor,
    merge_PM2R_it,
    merge_PM2R_pop,
    merge_AlexL,
    merge_Laurent,
    merge_Shihab,
    merge_EvKounis,
    merge_vaultah,
)

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

def qdata_test():
    print('Testing all functions with the question data')
    alist, blist, chooser = (
        ['b', 'c'],
        ['BMW', 'VW', 'Volvo'], 
        [True, True, False, True, False],
    )

    expected = ['BMW', 'VW', 'b', 'Volvo', 'c']
    print('Expected:', expected)
    for func in funcs:
        print(func.__name__, func(alist, blist, chooser) == expected)

def make_data(size):
    ''' Create two equal-sized data lists and a random chooser list '''
    a = list(range(1, size + 1))
    b = [-u for u in a]
    c = [False] * size + [True] * size
    shuffle(c)
    return a, b, c

def verify():
    results = [func(alist, blist, chooser) for func in funcs]
    first = results[0]
    return all(first == u for u in results[1:])

def time_test(loops, reps):
    ''' Print timing stats for all the functions '''
    timings = []
    for func in funcs:
        fname = func.__name__
        setup = 'from __main__ import alist, blist, chooser, ' + fname
        cmd = '{0}(alist, blist, chooser)'.format(fname)
        t = Timer(cmd, setup)
        result = t.repeat(reps, loops)
        result.sort()
        timings.append((result, fname))

    timings.sort()
    for result, fname in timings:
        print('{0:18} {1}'.format(fname, result))

qdata_test()

maxloops = 5 ** 7
for i in range(1, 7):
    size = 5 ** i
    loops, reps = maxloops // size, 3
    print('\nList size = {0}, loops = {1}'.format(size, loops))

    alist, blist, chooser = make_data(size)
    print('All functions verified', verify())

    time_test(loops, reps)    

Python 3输出

Testing all functions with the question data
Expected: ['BMW', 'VW', 'b', 'Volvo', 'c']
merge_wwii_ifelse True
merge_wwii_andor True
merge_PM2R_it True
merge_PM2R_pop True
merge_AlexL True
merge_Laurent True
merge_Shihab True
merge_EvKounis True
merge_vaultah True

List size = 5, loops = 15625
All functions verified True
merge_Shihab       [0.1553873940010817, 0.15573736099941016, 0.1570748160011135]
merge_vaultah      [0.19238512099946092, 0.19444048600053065, 0.19622620799964352]
merge_wwii_ifelse  [0.1928826420007681, 0.20096588600063114, 0.2038269639997452]
merge_wwii_andor   [0.19839437199880194, 0.19887267900048755, 0.1997791949997918]
merge_PM2R_it      [0.21258554000087315, 0.21627756400084763, 0.21734632500010775]
merge_Laurent      [0.22584542599906854, 0.22584707799978787, 0.2275525179993565]
merge_PM2R_pop     [0.252919409000242, 0.2563238849998015, 0.28485306599941396]
merge_AlexL        [0.295069166999383, 0.2970452879999357, 0.3192335510011617]
merge_EvKounis     [0.3210714779997943, 0.32545770300021104, 0.3283817559986346]

List size = 25, loops = 3125
All functions verified True
merge_wwii_andor   [0.13853849199949764, 0.13861457399980281, 0.16665312800068932]
merge_vaultah      [0.1385455899999215, 0.13872790400091617, 0.13888424499964458]
merge_wwii_ifelse  [0.14001116700092098, 0.1411627879988373, 0.14938874099971144]
merge_PM2R_pop     [0.1415618489991175, 0.14180967100037378, 0.14234910300001502]
merge_Shihab       [0.1417505749996053, 0.14575945399883494, 0.1469801869989169]
merge_PM2R_it      [0.15280632599933597, 0.1578172520003136, 0.20611876800103346]
merge_Laurent      [0.15372244299942395, 0.15373632599948905, 0.15608775699911348]
merge_AlexL        [0.19783953799924348, 0.19835066099949472, 0.19853855400106113]
merge_EvKounis     [0.21501469599934353, 0.21525065300011192, 0.21861338300004718]

List size = 125, loops = 625
All functions verified True
merge_PM2R_pop     [0.10481183099909686, 0.10530150200065691, 0.1054428099996585]
merge_vaultah      [0.12480986199989275, 0.125469589000204, 0.12560611799926846]
merge_wwii_andor   [0.1248406070008059, 0.1251086979991669, 0.12896737399933045]
merge_wwii_ifelse  [0.1248461369996221, 0.12487849500030279, 0.1357243729999027]
merge_Shihab       [0.13901417600027344, 0.14433371599989187, 0.14757765399917844]
merge_Laurent      [0.14081091899970488, 0.14126963899980183, 0.21554046200071753]
merge_PM2R_it      [0.14273404000050505, 0.1436745359987981, 0.14957189699998708]
merge_AlexL        [0.1876233860002685, 0.18891249499938567, 0.2016287040005409]
merge_EvKounis     [0.20533967399933317, 0.2060009060005541, 0.2169854090006993]

List size = 625, loops = 125
All functions verified True
merge_PM2R_pop     [0.10215267800049332, 0.10283978299958108, 0.10370849799983262]
merge_vaultah      [0.12245723900014127, 0.1226432970015594, 0.12315383100030886]
merge_wwii_ifelse  [0.12513774199942418, 0.12616848099969502, 0.12886606600113737]
merge_wwii_andor   [0.12801914100055, 0.12805822200061812, 0.12933381000038935]
merge_PM2R_it      [0.137118164999265, 0.13727735000065877, 0.1388498169999366]
merge_Laurent      [0.138064671000393, 0.1399875509996491, 0.1408491909987788]
merge_Shihab       [0.14056324699959077, 0.14599118399928557, 0.190011668999432]
merge_AlexL        [0.2494661869986885, 0.24949409599867067, 0.25023536899971077]
merge_EvKounis     [0.2604512350008008, 0.2616422920000332, 0.26348238600076]

List size = 3125, loops = 25
All functions verified True
merge_PM2R_pop     [0.10108045999913884, 0.1956245539986412, 0.19625802900009148]
merge_vaultah      [0.1205880960005743, 0.12112638399958087, 0.12208285199994862]
merge_wwii_andor   [0.12255161999928532, 0.12333094499990693, 0.12521908300004725]
merge_wwii_ifelse  [0.12545375700028671, 0.12909694299924013, 0.1335049829995114]
merge_PM2R_it      [0.13350266700035718, 0.1339889190003305, 0.13768064900068566]
merge_Laurent      [0.13691045599989593, 0.1544653910004854, 0.15945969300082652]
merge_Shihab       [0.13996293700074602, 0.14073836100033077, 0.15528064499994798]
merge_AlexL        [0.5525499420000415, 0.562283696999657, 0.954857885999445]
merge_EvKounis     [0.5699720739994518, 0.5713485720007156, 0.57778780100125]

List size = 15625, loops = 5
All functions verified True
merge_PM2R_pop     [0.10786392400041223, 0.10926139099865395, 0.10992666599850054]
merge_vaultah      [0.12552327299999888, 0.1260173209993809, 0.126270750999538]
merge_wwii_ifelse  [0.13077028499901644, 0.13549192800019227, 0.13690466499974718]
merge_wwii_andor   [0.13939281700004358, 0.14145590299995092, 0.1771287490009854]
merge_Laurent      [0.14111154199963494, 0.141571592001128, 0.14596649399936723]
merge_PM2R_it      [0.14352190899990092, 0.1444555029993353, 0.1446186849989317]
merge_Shihab       [0.1475988830006827, 0.14831254499949864, 0.15240716699918266]
merge_AlexL        [2.040518506999433, 2.0523803409996617, 2.1246015890010312]
merge_EvKounis     [2.0611778700003924, 2.0809960999995383, 2.0933345120010927]

Python 2输出

Testing all functions with the question data
Expected: ['BMW', 'VW', 'b', 'Volvo', 'c']
merge_wwii_ifelse True
merge_wwii_andor True
merge_PM2R_it True
merge_PM2R_pop True
merge_AlexL True
merge_Laurent True
merge_Shihab True
merge_EvKounis True
merge_vaultah True

List size = 5, loops = 15625
All functions verified True
merge_wwii_ifelse  [0.13266801834106445, 0.13341188430786133, 0.14590716361999512]
merge_vaultah      [0.1372370719909668, 0.20317387580871582, 0.28184700012207031]
merge_wwii_andor   [0.1373291015625, 0.14022302627563477, 0.14162182807922363]
merge_Shihab       [0.14127588272094727, 0.14717292785644531, 0.15103507041931152]
merge_PM2R_it      [0.16237378120422363, 0.16309309005737305, 0.1668241024017334]
merge_Laurent      [0.18718504905700684, 0.21074390411376953, 0.24513697624206543]
merge_PM2R_pop     [0.28445720672607422, 0.29493808746337891, 0.32616496086120605]
merge_EvKounis     [0.29379916191101074, 0.33054614067077637, 0.34055399894714355]
merge_AlexL        [0.29791903495788574, 0.29801201820373535, 0.31824994087219238]

List size = 25, loops = 3125
All functions verified True
merge_vaultah      [0.10121989250183105, 0.10190892219543457, 0.10230588912963867]
merge_wwii_andor   [0.10298919677734375, 0.10324811935424805, 0.1042180061340332]
merge_wwii_ifelse  [0.10428714752197266, 0.1065058708190918, 0.13893890380859375]
merge_PM2R_it      [0.11803603172302246, 0.11927890777587891, 0.12329411506652832]
merge_Shihab       [0.12048506736755371, 0.1209111213684082, 0.14031100273132324]
merge_Laurent      [0.12093997001647949, 0.12250900268554688, 0.12366700172424316]
merge_PM2R_pop     [0.14476203918457031, 0.14788198471069336, 0.15009903907775879]
merge_AlexL        [0.2096550464630127, 0.2101140022277832, 0.21013402938842773]
merge_EvKounis     [0.22748994827270508, 0.24114799499511719, 0.27338886260986328]

List size = 125, loops = 625
All functions verified True
merge_wwii_ifelse  [0.093290090560913086, 0.095035076141357422, 0.10503697395324707]
merge_wwii_andor   [0.095438957214355469, 0.096124887466430664, 0.096685171127319336]
merge_vaultah      [0.096237897872924805, 0.096857070922851562, 0.10109710693359375]
merge_Laurent      [0.11233901977539062, 0.11253595352172852, 0.11261391639709473]
merge_PM2R_it      [0.11286282539367676, 0.11314296722412109, 0.11331295967102051]
merge_PM2R_pop     [0.11631202697753906, 0.11657595634460449, 0.11874699592590332]
merge_Shihab       [0.12019991874694824, 0.12040495872497559, 0.12069797515869141]
merge_AlexL        [0.21399688720703125, 0.21718001365661621, 0.23727011680603027]
merge_EvKounis     [0.22643208503723145, 0.22728395462036133, 0.22952795028686523]

List size = 625, loops = 125
All functions verified True
merge_wwii_ifelse  [0.091418981552124023, 0.091669797897338867, 0.097893953323364258]
merge_vaultah      [0.092507839202880859, 0.09267878532409668, 0.09857487678527832]
merge_wwii_andor   [0.094152212142944336, 0.094262123107910156, 0.095048904418945312]
merge_PM2R_pop     [0.10612797737121582, 0.10874819755554199, 0.15479302406311035]
merge_Laurent      [0.10751605033874512, 0.10817885398864746, 0.1108400821685791]
merge_PM2R_it      [0.10856819152832031, 0.10870695114135742, 0.10909485816955566]
merge_Shihab       [0.12109684944152832, 0.12231802940368652, 0.12318301200866699]
merge_AlexL        [0.26717281341552734, 0.27173185348510742, 0.27331304550170898]
merge_EvKounis     [0.27798080444335938, 0.27915000915527344, 0.28347897529602051]

List size = 3125, loops = 25
All functions verified True
merge_wwii_ifelse  [0.089553117752075195, 0.090708017349243164, 0.096336126327514648]
merge_wwii_andor   [0.092846870422363281, 0.092998027801513672, 0.09307098388671875]
merge_vaultah      [0.093343973159790039, 0.096785068511962891, 0.11030793190002441]
merge_Laurent      [0.10524392127990723, 0.10576510429382324, 0.10692310333251953]
merge_PM2R_pop     [0.10529899597167969, 0.10684394836425781, 0.1188349723815918]
merge_PM2R_it      [0.1075129508972168, 0.1087181568145752, 0.11004185676574707]
merge_Shihab       [0.12116694450378418, 0.1221461296081543, 0.12650799751281738]
merge_AlexL        [0.57863092422485352, 0.58119797706604004, 0.62129878997802734]
merge_EvKounis     [0.59500694274902344, 0.59542298316955566, 0.59793877601623535]

List size = 15625, loops = 5
All functions verified True
merge_wwii_ifelse  [0.093538999557495117, 0.094748973846435547, 0.099496126174926758]
merge_wwii_andor   [0.097050189971923828, 0.097167015075683594, 0.14334392547607422]
merge_vaultah      [0.097479820251464844, 0.097939968109130859, 0.10231399536132812]
merge_Laurent      [0.10894298553466797, 0.10906291007995605, 0.11107587814331055]
merge_PM2R_pop     [0.11378717422485352, 0.11389708518981934, 0.11422491073608398]
merge_PM2R_it      [0.11379504203796387, 0.1164860725402832, 0.11690497398376465]
merge_Shihab       [0.12729287147521973, 0.12743711471557617, 0.12863397598266602]
merge_AlexL        [2.062777042388916, 2.0632898807525635, 2.104421854019165]
merge_EvKounis     [2.0776879787445068, 2.1075038909912109, 2.1273050308227539]

这些结果来自我相当古老的32位单核2GHZ机器,2GB内存运行Linux的Debian衍生物。

答案 2 :(得分:2)

>>> lyst = [True,True,False,True,False]
>>> car = ['BMW','VW','Volvo']
>>> a = ['b', 'c']
>>> [car.pop(0) if item else a.pop(0) for item in lyst]
['BMW', 'VW', 'b', 'Volvo', 'c']
>>> 

答案 3 :(得分:2)

我的第一个想法是使用dictTrue值( car )和False值之间进行选择( a )。

因为值是有序的,所以你可以进行迭代。

以下是使用有效的iter()next()函数的解决方案:

lyst = [True, True, False, True, False]
car = ['BMW', 'VW', 'Volvo']
a = ['b', 'c']

selector = {True: iter(car), False: iter(a)}
result = [next(selector[flag]) for flag in lyst]
print(result)
# -> ['BMW', 'VW', 'b', 'Volvo', 'c']

如果您的选择比True / False更复杂,则可以概括此解决方案。

答案 4 :(得分:2)

@Alex的代码很棒,但由于pop(0)操作的复杂性有点不好。为了避免这种情况 - “

>>> lyst = [True,True,False,True,False]
>>> car = ['BMW','VW','Volvo']
>>> a = ['b', 'c']
>>> i=0
>>> j=0
>>> ans=[]
>>> for v in lyst:
        if v:
            ans.append(car[i])
            i+=1
        else:
            ans.append(a[j])
            j+=1


>>> ans
['BMW', 'VW', 'b', 'Volvo', 'c']

至于其他答案,我对使用所有这些复杂的语法和数据结构来完成这么简单的任务感到有些惊讶。

答案 5 :(得分:0)

另一个选项很像@AlexL中的一个选项,但if语句被字典查找替换。

car = ["BMW", "VW", "Volvo"]
a = ["b", "c"]

my_list = [True, True, False, True, False]
mapping = {True: car, False: a}

new_list = [mapping[c].pop(0) for c in my_list]