python - 啃书 第四章 组合数据

第4章 组合数据 4.7 典型案例 4.7.1 查找

查找

换了材料算是复习过一遍后,对iterable有了深一些的认识,再看书上的例子,很模拟~

题目:查找列表中是否包含某元素,这里以数字为例

a=[1,2,3,4,5]
fa=int(input("查找列表是否包含数字:"))
print("包含" if fa in a else "不包含")

这里犯过两次错误:

fa=input("查找列表是否包含数字:") # 这样获取的结果是字符串
fa=[int(input("查找列表是否包含数字:"))] # 这样获取的是列表,但:
列表的查找方法:
list1.conut(value) # 138 ns 如果返回值>0,则包含
list1.index(value) # 76.4 ns 如果不包含,会报错
value in list1 # 39.7 ns 包含,返回True,反之False 适用于iterable

最效率最安全的,也是为之而设计的就是in,方法1、会遍历所有元素,方法2、会记录位置,如果不存在,还会报错。
方法3,会因列表的长度,与方法2的差距缩小甚至反转

以上就是这波的内容,再来看看书中的例子,我不喜欢这本书,例子不够艺术。也有多处错误,算法也很一般!

list1=[3,6,1,9,5,8,7,4]
# key=int(input("请输入要查找的关键字:"))
key=3
num=-1
for i in range(len(list1)):
    if list1[i]==key:
        num=i
        break
if num!=-1:
    print("要查找的关键字%d索引为%d."%(key,num))
else:
    print("关键字%d查找失败"%key)

如果把上面的代码写成下面的

%%timeit
list1=[3,6,1,9,5,8,7,4]
# key=int(input("请输入要查找的关键字:"))
key=3
num=-1
if key in list1:
    print("要查找的关键字%d索引为%d."%(key,list1.index(key)))
else:
    print("关键字%d查找失败"%key)

发生了很偶然的事情,两者的运算时间都是102 µs。
但我记得在那里,有过一个用法,可以在一个流程中同时获取两个数据!

list1=[3,6,1,9,5,8,7,4]
# key=int(input("请输入要查找的关键字:"))
key=3
num=-1
for (i,k) in list(enumerate(list1)):
    if k==key:
        print("要查找的关键字%d索引为%d."%(key,i))
        break
    else:
        print("关键字%d查找失败"%key)

效率仍是魔鬼般的102 µs

看来不是书上的算法的问题,这确实是个麻烦的问题!

%%timeit
list1=[3,6,1,9,5,8,7,4]
# key=int(input("请输入要查找的关键字:"))
key=3
try:
    i=list1.index(key)
    print("要查找的关键字%d索引为%d"%(key,i))
except:
    print("关键字%d查找失败"%key)

99.8 µs

str中有个find,让我们试一下

s="".join(chr(i) for i in range(40000,40500))
#'鱀鱁鱂鱃鱄鱅鱆鱇鱈鱉鱊鱋鱌鱍鱎鱏鱐鱑鱒鱓鱔鱕鱖鱗鱘鱙鱚鱛鱜鱝鱞鱟鱠鱡鱢鱣鱤鱥鱦鱧鱨鱩鱪鱫鱬鱭鱮鱯鱰鱱鱲鱳鱴鱵鱶鱷鱸鱹鱺鱻鱼鱽鱾鱿鲀鲁鲂鲃鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳚鳛鳜鳝鳞鳟鳠鳡鳢鳣鳤鳥鳦鳧鳨鳩鳪鳫鳬鳭鳮鳯鳰鳱鳲鳳鳴鳵鳶鳷鳸鳹鳺鳻鳼鳽鳾鳿鴀鴁鴂鴃鴄鴅鴆鴇鴈鴉鴊鴋鴌鴍鴎鴏鴐鴑鴒鴓鴔鴕鴖鴗鴘鴙鴚鴛鴜鴝鴞鴟鴠鴡鴢鴣鴤鴥鴦鴧鴨鴩鴪鴫鴬鴭鴮鴯鴰鴱鴲鴳鴴鴵鴶鴷鴸鴹鴺鴻鴼鴽鴾鴿鵀鵁鵂鵃鵄鵅鵆鵇鵈鵉鵊鵋鵌鵍鵎鵏鵐鵑鵒鵓鵔鵕鵖鵗鵘鵙鵚鵛鵜鵝鵞鵟鵠鵡鵢鵣鵤鵥鵦鵧鵨鵩鵪鵫鵬鵭鵮鵯鵰鵱鵲鵳鵴鵵鵶鵷鵸鵹鵺鵻鵼鵽鵾鵿鶀鶁鶂鶃鶄鶅鶆鶇鶈鶉鶊鶋鶌鶍鶎鶏鶐鶑鶒鶓鶔鶕鶖鶗鶘鶙鶚鶛鶜鶝鶞鶟鶠鶡鶢鶣鶤鶥鶦鶧鶨鶩鶪鶫鶬鶭鶮鶯鶰鶱鶲鶳鶴鶵鶶鶷鶸鶹鶺鶻鶼鶽鶾鶿鷀鷁鷂鷃鷄鷅鷆鷇鷈鷉鷊鷋鷌鷍鷎鷏鷐鷑鷒鷓鷔鷕鷖鷗鷘鷙鷚鷛鷜鷝鷞鷟鷠鷡鷢鷣鷤鷥鷦鷧鷨鷩鷪鷫鷬鷭鷮鷯鷰鷱鷲鷳鷴鷵鷶鷷鷸鷹鷺鷻鷼鷽鷾鷿鸀鸁鸂鸃鸄鸅鸆鸇鸈鸉鸊鸋鸌鸍鸎鸏鸐鸑鸒鸓鸔鸕鸖鸗鸘鸙鸚鸛鸜鸝鸞鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳'
%%timeit
s.index('鸳')
276 ns ± 6.62 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
s.find('鸳')
264 ns ± 5.49 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
s.count('鸳')
503 ns ± 6.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

没意思,给自己出道题吧!

%%timeit
i=s.count('鸳')
c=[]
a=0
while i:
    c.append(a:=s.find('鸳',a))
    i-=1
    a+=1
c # [106, 249, 355, 500]
2.15 µs ± 70.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

纳尼?

%%timeit
i=ss.count('鸳')
c=[]
a=0
while i:
    c.append(a:=ss.index('鸳',a))
    i-=1
    a+=1
19.1 µs ± 422 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
ss.index('鸳')
1.96 µs ± 14.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
s.index('鸳')
188 ns ± 1.6 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

列表的索引操作相对字符串,慢

但:
%%timeit
ss=list(s)
22.7 µs ± 197 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

二分查找

条件:有序数列,升序或降序
假定升序:先查找最中间的,如果key>list1[len(list1)//2],则查找后半段中间的,依次!

def Binary_Search(start,end):
    m=start+(end-start)//2
    lm=list1[m]
    if key==lm:
        print("%d在列表的索引%d"%(key,m))
    elif key>lm:
        Binary_Search(m+1,end)
    else:Binary_Search(start,m)

list1=list(range(100))
start=0
end=len(list1)-1
key=int(input("请输入要查找的数字:"))
if key<list1[start] or key>list1[end]:
    print("key不在列表范围内")
else:Binary_Search(start,end)

以上出现了两次书写错误,input没有int,想着来着,想先写完input回头用int括起来,结果写完就顺着写下去了,忘了。
又把list1写成list了,少了1。其实我宁愿写l,例如m就是middle,我本来吧m和lm用全写写出来了,又改回去了,我不喜欢这种命名。觉得反而会让代码看着乱。在这,start、end,这么明显了,还来?
30:108 µs
和常规顺序查找效率差不多
80:也是这个数,但是常规查找是114 µs
理论上二分查找较常规查找更有优势,但是前提是顺序序列

列表的索引是从末尾开始的

list1[0]
51 ns ± 14.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
list1[99]
42.3 ns ± 2.14 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
list1[50]
48.5 ns ± 6.08 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
list1[50]
list1[50]
list1[50]
127 ns ± 8.74 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
100
11.9 ns ± 0.878 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
a
25.6 ns ± 3.28 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
a=100
33.2 ns ± 2.83 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
a=100
a
47.5 ns ± 2.51 ns per loop (mean ± std. dev. of 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值