社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python——从一个列表切换到另一个列表(最佳方式)

VeljkoSbbb • 3 年前 • 1189 次点击  

我有两份清单

list1 = [1, 3, 5, 8]
list2 = [7, 10, 12]

还有一些破坏int值 switchValue = 4 我需要反复浏览 list1 而其元素的价值小于 switchValue ,然后迭代整个 list2 1.我知道如何使用 if break 声明 else 分支,但我正在研究如何在Python2.7中实现这一点的一些更优化(推荐)的方法,因为这些列表将非常大。此外,还会对列表进行排序。

result 应该是 1, 3, 7, 10, 12

list1 = [1, 3, 5, 8]
list2 = [7, 10, 12]
switchValue = 4
for i in list1:
    if i < switchValue:
        print(i)
    else:
        for j in list2:
            print(j)
        break
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/131527
 
1189 次点击  
文章 [ 2 ]  |  最新文章 3 年前
Kelly Bundy
Reply   •   1 楼
Kelly Bundy    3 年前

您可以使用二进制搜索来查找开关索引:

from bisect import bisect_left
switchIndex = bisect_left(list1, switchValue)

然后在不使用Python循环的情况下打印(哦,在Python 2中不起作用,但下面的另一个可以):

print(*list1[:switchIndex], sep='\n')
print(*list2, sep='\n')

或者:

print('\n'.join(map(str, list1[:switchIndex])))
print('\n'.join(map(str, list2)))

在Python 2中,在10万倍长的列表上与您和deceze的列表一起进行基准测试:

 51 ms   52 ms   52 ms  Kelly2
137 ms  138 ms  138 ms  original
138 ms  138 ms  138 ms  deceze1
160 ms  160 ms  161 ms  deceze2
164 ms  164 ms  165 ms  deceze3

在Python 3中:

111 ms  114 ms  114 ms  Kelly2
134 ms  134 ms  135 ms  Kelly1
176 ms  177 ms  178 ms  deceze1
178 ms  178 ms  178 ms  original
189 ms  189 ms  191 ms  deceze2
191 ms  192 ms  192 ms  deceze3

(不包括@buhtz's,因为它不太具有可比性。)

基准代码( Try it online! - Python 2 version ):

def original():
    for i in list1:
        if i < switchValue:
            print(i)
        else:
            for j in list2:
                print(j)
            break

def deceze1():
    for i in list1:
        if i >= switchValue:
            break
        print(i)
    for i in list2:
        print(i)

def deceze2():
    for i in takewhile(lambda i: i < switchValue, list1):
        print(i)
    for i in list2:
        print(i)

def deceze3():
    for i in chain(takewhile(lambda i: i < switchValue, list1), list2):
        print(i)

def Kelly1():
    switchIndex = bisect_left(list1, switchValue)
    print(*list1[:switchIndex], sep='\n')
    print(*list2, sep='\n')

def Kelly2():
    switchIndex = bisect_left(list1, switchValue)
    print('\n'.join(map(str, list1[:switchIndex])))
    print('\n'.join(map(str, list2)))

funcs = original, deceze1, deceze2, deceze3, Kelly1, Kelly2

import os, sys
from timeit import default_timer as timer
from bisect import bisect_left
from itertools import takewhile, chain

list1 = [1, 3, 5, 8]
list2 = [7, 10, 12]
switchValue = 4

for func in funcs:
    print(func.__name__ + ':')
    func()

n = 100_000
list1 = [x for x in list1 for _ in range(n)]
list2 = [x for x in list2 for _ in range(n)]

print('benchmark:')
tss = [[] for _ in funcs]
for _ in range(10):
    for func, ts in zip(funcs, tss):
        with open(os.devnull, 'w') as sys.stdout:
            t0 = timer()
            func()
            t1 = timer()
        sys.stdout = sys.__stdout__
        ts.append(t1 - t0)
        ts.sort()
for func, ts in sorted(zip(funcs, tss), key=lambda x: x[1]):
    print(*('%d ms ' % (t * 1e3) for t in sorted(ts)[:3]), func.__name__)
deceze
Reply   •   2 楼
deceze    3 年前
for i in list1:
    if i >= switchValue:
        break
    print(i)

for i in list2:
    print(i)

这就是你想要的。反复浏览 list1 直到找到一个特定的值,然后停止遍历 清单1 .然后遍历完整的 list2 .这两件事似乎是完全独立的行动,因此没有必要将它们交织在同一个循环中。

请注意,这假设您 总是 想要迭代吗 清单2 ,而不仅仅是当你遇到 switchValue .你的问题在那一点上并不完全清楚。

第一次迭代可以用以下内容来修饰 itertools.takewhile :

for i in takewhile(lambda i: i < switchValue, list1):
    print(i)

for i in list2:
    print(i)

要将两者放在同一个循环中,您可以 chain 他们:

for i in chain(takewhile(lambda i: i < switchValue, list1), list2):
    print(i)