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

Posted

技术标签:

【中文标题】python - 用两个不同列表中的值替换列表的布尔值[重复]【英文标题】:python - replace the boolean value of a list with the values from two different lists [duplicate] 【发布时间】:2017-06-21 01:58:18 【问题描述】:

我有一个带有布尔值的列表,例如

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

还有两个不同的列表,例如:

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

我只想用car 中的值替换True,用a 中的值替换False。 或使用来自lyst 的序列和来自cara 的值创建一个新列表。 结果应该是

[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 的列表匹配。

我该怎么做?

【问题讨论】:

如果list 中的True 项目数大于car 中的项目数怎么办?此外,您应该避免将名称 list 用于变量。 @ason​​gtoruin False ofc 也是如此。 这会有点争议...作为一个新手,我可以向你保证,当你用 iter 、next 或复杂的列表理解来回答这样一个简单的问题时,你只是在鼓励新手谁问这个问题只是复制/粘贴代码而不试图理解实际发生的事情。我知道,这些是做事的正确方式,你必须注意它们。但首先是一个简单的答案。 您可能对我刚刚添加到答案中的计时脚本和数据感兴趣。 【参考方案1】:
>>> 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']
>>> 

【讨论】:

if sum(lyst) 您可能对我刚刚添加到答案中的计时脚本和数据感兴趣。【参考方案2】:
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,则可能会出现问题。这也不像第一个解决方案中的三元那样可读。

但这很有趣。


我想我会在再次查看此内容后补充一点,我可能不应该重新分配原始列表名称 - 我应该为迭代器名称选择不同的名称。一旦用尽,迭代器就不能重置,而且由于列表名称被重新分配,原始列表信息丢失。

【讨论】:

是的,这是我的想法。我不禁觉得有一些结构可以让它变得更好。 @Mitch 类似于numpy.where。我查看了 itertools,但找不到更好的东西。 我和你在一起 - 想不出任何 atm。不错的答案,+1 :) 第一个代码运行良好。与您的第二个代码有什么区别? @二战 感谢您提及and ... or 方法的缺陷(当所需项目之一可能是假的时)。在 Python 的早期,当我们没有三元条件表达式时,这曾经困扰过很多人,所以 and ... or 构造的使用比在现代 Python 中要普遍得多。【参考方案3】:

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

由于值是有序的,您可以进行迭代。

这是一个使用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】:

假设lyst 中有正确数量的TrueFalse 条目,您可以通过创建其他两个列表的迭代器来有效地做到这一点。这比列表前面的poping 效率更高。

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://***.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 RAM,运行 Linux 的 Debian 衍生产品。

【讨论】:

【参考方案5】:

只是另一个选项,很像来自@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]

【讨论】:

您可能对我刚刚添加到答案中的计时脚本和数据感兴趣。【参考方案6】:

@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']

至于其他答案,看到如此简单的任务使用所有这些复杂的语法和数据结构,我有点惊讶。

【讨论】:

使用iternext 并不复杂。 Pythonistas 竭尽全力避免通过索引访问列表,除非这是不可避免的。 ;) 我还是有点新手知道,通过索引访问列表有什么问题? FWIW,避免.pop(0) 效率低下的另一种方法是从其他两个列表中迭代reversed(lyst)pop()。然后你必须反转结果列表,当然,但这相当有效(肯定比通过预先挂起创建结果列表更有效)。 哦,通过索引间接访问并没有什么错误,但是使用索引通常会给代码增加混乱,并且效率低于直接迭代。使用 range 生成索引并不算太糟糕,因为它以 C 速度进行算术运算,但使用 Python 算术自己维护索引(如 i+=1)相对较慢。 现在这真是一个优化。

以上是关于python - 用两个不同列表中的值替换列表的布尔值[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python - 如何用不同的值替换相邻的列表元素

如何替换python列表特定索引处的值?

Python 替换列表中的值

替换 Python 列表/字典中的值?

用列表 Pyspark Dataframe 中的值替换 NA

用列表的值替换 numpy 索引数组的值