[英]fast ordered sort (and extract from) tuple based on list
我是python新手,我一直在嘗試根據列表中的值對元組中的值進行排序(提取),但是到目前為止,我的代碼似乎真的很慢。
所以,我有一個像這樣的列表:
x = ["d5b44796d43c4bf5a0f252aeb49738f5", "04d0e11f8ceb4b128fa723181369ba1a", "6244dd8bfee44a61800a25d9f2e6f743", "662ae26640a44a37816daa6e85ef4972", "7d5e1f59f7984495877a059bea643954"]
的,我有一個像這樣的元組:
y = [(31, u'dir/04d0e11f8ceb4b128fa723181369ba1a.mov'), (32, u'dir/d5b44796d43c4bf5a0f252aeb49738f5.pdf'), (66, u'dir/6244dd8bfee44a61800a25d9f2e6f743.jpg'), (34, u'dir/662ae26640a44a37816daa6e85ef4972.doc'), (33, u'dir/7d5e1f59f7984495877a059bea643954.ppt')]
如果x
的元素存在於y[i][1]
我想從y
獲取id
。 因此,如下所示:
id_list=[]
for i in x:
for j in y:
if i in j[1]:
try:
id_list.append(j[0])
except:
pass
break
else:
pass
我得到:
id_list = [32, 31, 66, 34, 33]
同樣,結果集必須保持x
的順序。 上面的循環可以做到這一點。
問題是上面的代碼非常慢(羞愧!)-我的x
在1000的范圍內,而y
也在。
所以我想我的問題是是否有更好的方法編寫上述代碼? 我在這里正在考慮迭代器,但並不確定在這種情況下如何編寫迭代器。
id_list = [j[0] for j in sorted(y, key=lambda e: x.index(e[1].split('/')[-1].split('.')[0]))]
如果x是dict
則可以改進此方法,因為查找會更快,因此我們將使用OrderedDict
來維護順序:
import collections
from os.path import basename, splitext
x = collections.OrderedDict((e, i) for i, e in enumerate(x))
id_list = [j[0] for j in sorted(y, key=lambda e: x[splitext(basename(e[1]))[0]])]
In [3]y1=[elem[1].strip('dir').split('.')[0] for elem in y]
In [4]: res=[(i,j[0]) for i in x for j in y1 if i in j ]
In [5]: res
Out[5]:
[('04d0e11f8ceb4b128fa723181369ba1a', 31),
('6244dd8bfee44a61800a25d9f2e6f743', 66),
('662ae26640a44a37816daa6e85ef4972', 34),
('7d5e1f59f7984495877a059bea643954', 33)]
In [6]: [elem[1] for elem in res]
Out[6]: [31, 66, 34, 33]
如果要保持x的順序,則需要提取y
所有id並將它們放在集合中,然后在x上進行迭代以檢查項是否在集合中:
>>> x = ["d5b44796d43c4bf5a0f252aeb49738f5", "04d0e11f8ceb4b128fa723181369ba1a", "6244dd8bfee44a61800a25d9f2e6f743", "662ae26640a44a37816daa6e85ef4972", "7d5e1f59f7984495877a059bea643954"]
>>> y = [(31, u'dir/04d0e11f8ceb4b128fa723181369ba1a.mov'), (32, u'dir/d5b44796d43c4bf5a0f252aeb49738f5.pdf'), (66, u'dir/6244dd8bfee44a61800a25d9f2e6f743.jpg'), (34, u'dir/662ae26640a44a37816daa6e85ef4972.doc'), (33, u'dir/7d5e1f59f7984495877a059bea643954.ppt')]
>>> s = set()
>>> for e in y:
... r = re.match(r'^dir/(.*)\.', e[1])
... if r:
... s.add(r.group(1))
>>> [e for e in x if e in s]
x = ["d5b44796d43c4bf5a0f252aeb49738f5", "04d0e11f8ceb4b128fa723181369ba1a", "6244dd8bfee44a61800a25d9f2e6f743", "662ae26640a44a37816daa6e85ef4972", "7d5e1f59f7984495877a059bea643954"]
xset = set(x)
y = [(31, u'dir/04d0e11f8ceb4b128fa723181369ba1a.mov'), (32, u'dir/d5b44796d43c4bf5a0f252aeb49738f5.pdf'), (66, u'dir/6244dd8bfee44a61800a25d9f2e6f743.jpg'), (34, u'dir/662ae26640a44a37816daa6e85ef4972.doc'), (33, u'dir/7d5e1f59f7984495877a059bea643954.ppt')]
print [num for num, path in y if path.split('/')[1].split('.')[0] in xset]
在這個答案中 :使用[:-4]
可能不是一個好主意,如果我們有dir/04d0e11f8ceb4b128fa723181369ba1a.rmvb
怎么dir/04d0e11f8ceb4b128fa723181369ba1a.rmvb
? 我建議使用os.path.splitext(os.path.basename(thefilepath))[0]
來獲取文件名。
所以我的想法是:我們首先將元素映射到id, yy
應該是:
{u'7d5e1f59f7984495877a059bea643954': 33,u'6244dd8bfee44a61800a25d9f2e6f743': 66, u'662ae26640a44a37816daa6e85ef4972': 34, u'04d0e11f8ceb4b128fa723181369ba1a': 31, u'd5b44796d43c4bf5a0f252aeb49738f5': 32}
並且我們使用yy[element]
獲得ID,其順序應與以前相同。
解決方案:
from os import path
yy = {path.splitext(path.basename(j))[0]:i for (i, j) in y}
xx = [yy[i] for i in x]
print(xx)
# output
[32, 31, 66, 34, 33]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.