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
的序列和来自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 的列表匹配。
我该怎么做?
【问题讨论】:
如果list
中的True
项目数大于car
中的项目数怎么办?此外,您应该避免将名称 list
用于变量。
@asongtoruin 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 的对象
如果 car
或 a
中的任何项目评估为 False,则可能会出现问题。这也不像第一个解决方案中的三元那样可读。
但这很有趣。
我想我会在再次查看此内容后补充一点,我可能不应该重新分配原始列表名称 - 我应该为迭代器名称选择不同的名称。一旦用尽,迭代器就不能重置,而且由于列表名称被重新分配,原始列表信息丢失。
【讨论】:
是的,这是我的想法。我不禁觉得有一些结构可以让它变得更好。 @Mitch 类似于numpy.where。我查看了 itertools,但找不到更好的东西。 我和你在一起 - 想不出任何 atm。不错的答案,+1 :) 第一个代码运行良好。与您的第二个代码有什么区别? @二战 感谢您提及and ... or
方法的缺陷(当所需项目之一可能是假的时)。在 Python 的早期,当我们没有三元条件表达式时,这曾经困扰过很多人,所以 and ... or
构造的使用比在现代 Python 中要普遍得多。【参考方案3】:
我的第一个想法是使用 dict
在 True
值 (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
中有正确数量的True
和False
条目,您可以通过创建其他两个列表的迭代器来有效地做到这一点。这比列表前面的pop
ing 效率更高。
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']
至于其他答案,看到如此简单的任务使用所有这些复杂的语法和数据结构,我有点惊讶。
【讨论】:
使用iter
和next
并不复杂。 Pythonistas 竭尽全力避免通过索引访问列表,除非这是不可避免的。 ;)
我还是有点新手知道,通过索引访问列表有什么问题?
FWIW,避免.pop(0)
效率低下的另一种方法是从其他两个列表中迭代reversed(lyst)
和pop()
。然后你必须反转结果列表,当然,但这相当有效(肯定比通过预先挂起创建结果列表更有效)。
哦,通过索引间接访问并没有什么错误,但是使用索引通常会给代码增加混乱,并且效率低于直接迭代。使用 range
生成索引并不算太糟糕,因为它以 C 速度进行算术运算,但使用 Python 算术自己维护索引(如 i+=1
)相对较慢。
现在这真是一个优化。以上是关于python - 用两个不同列表中的值替换列表的布尔值[重复]的主要内容,如果未能解决你的问题,请参考以下文章