दो तारों को एक साथ मिलाने का सबसे पैथोनिक तरीका क्या है?
उदाहरण के लिए:
इनपुट:
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
आउटपुट:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
दो तारों को एक साथ मिलाने का सबसे पैथोनिक तरीका क्या है?
उदाहरण के लिए:
इनपुट:
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
आउटपुट:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
जवाबों:
मेरे लिए, सबसे पाइथोनिक * तरीका निम्नलिखित है जो बहुत अधिक एक ही काम करता है लेकिन +प्रत्येक स्ट्रिंग में अलग-अलग वर्णों को संक्षिप्त करने के लिए ऑपरेटर का उपयोग करता है :
res = "".join(i + j for i, j in zip(u, l))
print(res)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
यह दो join()कॉल का उपयोग करने से भी तेज है :
In [5]: l1 = 'A' * 1000000; l2 = 'a' * 1000000
In [6]: %timeit "".join("".join(item) for item in zip(l1, l2))
1 loops, best of 3: 442 ms per loop
In [7]: %timeit "".join(i + j for i, j in zip(l1, l2))
1 loops, best of 3: 360 ms per loop
तेजी से दृष्टिकोण मौजूद हैं, लेकिन वे अक्सर कोड को बाधित करते हैं।
नोट: यदि दो इनपुट स्ट्रिंग्स समान लंबाई नहीं हैं , तो zipछोटी स्ट्रिंग के अंत में पुनरावृति को रोकने के लिए लंबे समय तक एक को छोटा किया जाएगा । इस मामले में zipएक के बजाय मॉड्यूल से zip_longest( izip_longestपायथन 2 में) का उपयोग करना चाहिए itertoolsताकि यह सुनिश्चित हो सके कि दोनों तार पूरी तरह से समाप्त हो गए हैं।
* पायथन के ज़ेन से एक उद्धरण लेने के लिए : पठनीयता मायने रखती है ।
पाइथोनिक = मेरे लिए पठनीयता ; i + jकम से कम मेरी आंखों के लिए बस नेत्रहीन रूप से अधिक आसानी से पार्स किया गया है।
"".join([i + j for i, j in zip(l1, l2)])और यह निश्चित रूप से सबसे तेज़ होगा
"".join(map("".join, zip(l1, l2)))यह और भी तेज है, हालांकि जरूरी नहीं कि अधिक पाइथोनिक हो।
दूसरा रास्ता:
res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
print(''.join(res))
आउटपुट:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
ऐसा लगता है कि यह तेज है:
%%timeit
res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
''.join(res)
100000 loops, best of 3: 4.75 µs per loop
अब तक के सबसे तेज समाधान की तुलना में:
%timeit "".join(list(chain.from_iterable(zip(u, l))))
100000 loops, best of 3: 6.52 µs per loop
इसके अलावा बड़े तार के लिए:
l1 = 'A' * 1000000; l2 = 'a' * 1000000
%timeit "".join(list(chain.from_iterable(zip(l1, l2))))
1 loops, best of 3: 151 ms per loop
%%timeit
res = [''] * len(l1) * 2
res[::2] = l1
res[1::2] = l2
''.join(res)
10 loops, best of 3: 92 ms per loop
पायथन 3.5.1।
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijkl'
zip()समतुल्य)min_len = min(len(u), len(l))
res = [''] * min_len * 2
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
print(''.join(res))
आउटपुट:
AaBbCcDdEeFfGgHhIiJjKkLl
itertools.zip_longest(fillvalue='')बराबर)min_len = min(len(u), len(l))
res = [''] * min_len * 2
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
res += u[min_len:] + l[min_len:]
print(''.join(res))
आउटपुट:
AaBbCcDdEeFfGgHhIiJjKkLlMNOPQRSTUVWXYZ
के साथ join()और zip()।
>>> ''.join(''.join(item) for item in zip(u,l))
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
''.join(itertools.chain.from_iterable(zip(u, l)))
zipरुक जाता है जब छोटी सूची पूरी तरह से खत्म हो गई है।
itertools.zip_longestअगर यह एक मुद्दा बन जाता है तो इसका इस्तेमाल किया जा सकता है।
अजगर 2 पर, द्वारा अब तक तेजी से जिस तरह से चीजें, छोटे तार के लिए सूची टुकड़ा करने की क्रिया और ~ लंबे लोगों के लिए 30x की गति करने के लिए ~ 3x पर, है
res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)
हालांकि यह पायथन 3 पर काम नहीं करेगा। आप कुछ इस तरह से लागू कर सकते हैं
res = bytearray(len(u) * 2)
res[::2] = u.encode("ascii")
res[1::2] = l.encode("ascii")
res.decode("ascii")
लेकिन तब तक आप पहले से ही छोटे तार के लिए सूचीकरण से अधिक लाभ खो चुके हैं (यह अभी भी 20x लंबी स्ट्रिंग के लिए गति है) और यह अभी तक गैर-एएससीआईआई पात्रों के लिए भी काम नहीं करता है।
FWIW, यदि आप बड़े पैमाने पर स्ट्रिंग्स पर यह कर रहे हैं और हर चक्र की आवश्यकता है, और किसी कारण से पायथन स्ट्रिंग्स का उपयोग करना है ... यहाँ यह कैसे करना है:
res = bytearray(len(u) * 4 * 2)
u_utf32 = u.encode("utf_32_be")
res[0::8] = u_utf32[0::4]
res[1::8] = u_utf32[1::4]
res[2::8] = u_utf32[2::4]
res[3::8] = u_utf32[3::4]
l_utf32 = l.encode("utf_32_be")
res[4::8] = l_utf32[0::4]
res[5::8] = l_utf32[1::4]
res[6::8] = l_utf32[2::4]
res[7::8] = l_utf32[3::4]
res.decode("utf_32_be")
विशेष-छोटे प्रकार के सामान्य मामले को भी मदद मिलेगी। एफडब्ल्यूआईडब्ल्यू, यह लंबी स्ट्रिंग्स के लिए सूची स्लाइसिंग की केवल 3x गति और छोटे स्ट्रिंग्स के लिए 4 से 5 धीमी का कारक है ।
किसी भी तरह से मैं joinसमाधान पसंद करता हूं , लेकिन चूंकि समय का उल्लेख कहीं और किया गया था, इसलिए मुझे लगा कि मैं इसमें शामिल हो सकता हूं।
यदि आप सबसे तेज़ तरीका चाहते हैं, तो आप itertools के साथ जोड़ सकते हैंoperator.add :
In [36]: from operator import add
In [37]: from itertools import starmap, izip
In [38]: timeit "".join([i + j for i, j in uzip(l1, l2)])
1 loops, best of 3: 142 ms per loop
In [39]: timeit "".join(starmap(add, izip(l1,l2)))
1 loops, best of 3: 117 ms per loop
In [40]: timeit "".join(["".join(item) for item in zip(l1, l2)])
1 loops, best of 3: 196 ms per loop
In [41]: "".join(starmap(add, izip(l1,l2))) == "".join([i + j for i, j in izip(l1, l2)]) == "".join(["".join(item) for item in izip(l1, l2)])
Out[42]: True
लेकिन संयोजन izipऔरchain.from_iterable फिर से तेज है
In [2]: from itertools import chain, izip
In [3]: timeit "".join(chain.from_iterable(izip(l1, l2)))
10 loops, best of 3: 98.7 ms per loop
वहाँ भी बीच बहुत अधिक अंतर है
chain(*औरchain.from_iterable(... ।
In [5]: timeit "".join(chain(*izip(l1, l2)))
1 loops, best of 3: 212 ms per loop
ज्वाइन के साथ जेनरेटर जैसी कोई चीज नहीं है, पासिंग हमेशा धीमी होती जा रही है क्योंकि अजगर पहले कंटेंट का इस्तेमाल करते हुए एक लिस्ट बनाएगा क्योंकि यह डेटा के ऊपर से दो पास करता है, एक को साइज का पता लगाना होता है और एक को असल में करना होता है। जो एक जनरेटर का उपयोग करना संभव नहीं होगा:
join.h :
/* Here is the general case. Do a pre-pass to figure out the total
* amount of space we'll need (sz), and see whether all arguments are
* bytes-like.
*/
यदि आपके पास अलग-अलग लंबाई के तार हैं और आप डेटा नहीं खोना चाहते हैं तो आप izip_longest का उपयोग कर सकते हैं :
In [22]: from itertools import izip_longest
In [23]: a,b = "hlo","elworld"
In [24]: "".join(chain.from_iterable(izip_longest(a, b,fillvalue="")))
Out[24]: 'helloworld'
अजगर 3 के लिए इसे कहा जाता है zip_longest
लेकिन python2 के लिए, वेद्रेक का सुझाव अब तक का सबसे तेज़ है:
In [18]: %%timeit
res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)
....:
100 loops, best of 3: 2.68 ms per loop
list?? अनलाइडेड है
"".join(list(...))मुझे समय देने के लिए 6.715280318699769 और मुझे समय "".join(starmap(...))देने के लिए 6.46332361384313
"".join(list(starmap(add, izip(l1,l2))))तुलना में धीमी है "".join(starmap(add, izip(l1,l2)))। मैं अपनी मशीन में अजगर 2.7.11 में और अजगर 3.5.1 में भी www.python.org के वर्चुअल कंसोल में अजगर 3.4.3 के साथ दौड़ता हूं और सभी यही कहते हैं और मैं इसे एक-दो बार चलाता हूं और हमेशा वही
आप इसका उपयोग भी कर सकते हैं mapऔर operator.add:
from operator import add
u = 'AAAAA'
l = 'aaaaa'
s = "".join(map(add, u, l))
आउटपुट :
'AaAaAaAaAa'
मैप क्या करता है, यह प्रत्येक तत्व को पहली पुनरावृत्ति से लेता है uऔर दूसरे पुनरावृत्ति से पहले तत्वों lको पहले तर्क के रूप में दिए गए फ़ंक्शन को लागू करता है add। फिर जुड़ते हैं बस उनसे जुड़ते हैं।
इनमें से बहुत सारे सुझाव यह मानते हैं कि तार समान लंबाई के हैं। हो सकता है कि यह सभी उचित उपयोग के मामलों को कवर करता हो, लेकिन कम से कम मुझे ऐसा लगता है कि आप अलग-अलग लंबाई के तारों को भी जोड़ना चाह सकते हैं। या मैं केवल एक ही सोच रहा हूँ कि मेष को इस तरह से काम करना चाहिए:
u = "foobar"
l = "baz"
mesh(u,l) = "fboaozbar"
ऐसा करने का एक तरीका निम्नलिखित होगा:
def mesh(a,b):
minlen = min(len(a),len(b))
return "".join(["".join(x+y for x,y in zip(a,b)),a[minlen:],b[minlen:]])
मुझे दो forएस का उपयोग करना पसंद है , चर नाम एक संकेत / अनुस्मारक दे सकता है कि क्या हो रहा है:
"".join(char for pair in zip(u,l) for char in pair)
O- (1) प्रयास के साथ n स्ट्रिंग को संभालने के लिए यहां डबल-लिस्ट-कॉम्प्रिहेंशन उत्तर पर विचार नहीं करने के लिए थोड़ा अन-पायथोनिक लगता है:
"".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)
जहाँ all_stringsआप में हस्तक्षेप करने के लिए चाहते तार की एक सूची है। आपके मामले में, all_strings = [u, l]। एक पूर्ण उपयोग उदाहरण इस तरह दिखेगा:
import itertools
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
b = 'abcdefghijklmnopqrstuvwxyz'
all_strings = [a,b]
interleaved = "".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)
print(interleaved)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
कई जवाबों की तरह, सबसे तेज़? शायद नहीं, लेकिन सरल और लचीला। इसके अलावा, बहुत अधिक जटिल जटिलता के बिना, यह स्वीकृत उत्तर की तुलना में थोड़ा तेज है (सामान्य तौर पर, अजगर में स्ट्रिंग जोड़ थोड़ा धीमा है):
In [7]: l1 = 'A' * 1000000; l2 = 'a' * 1000000;
In [8]: %timeit "".join(a + b for i, j in zip(l1, l2))
1 loops, best of 3: 227 ms per loop
In [9]: %timeit "".join(c for cs in zip(*(l1, l2)) for c in cs)
1 loops, best of 3: 198 ms per loop
वर्तमान अग्रणी समाधान की तुलना में संभावित रूप से तेज़ और कम:
from itertools import chain
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
res = "".join(chain(*zip(u, l)))
रणनीति गति-वार सी-लेवल पर अधिक से अधिक संभव है। समान zip_longest () असमान तारों के लिए ठीक है और यह चेन () के रूप में एक ही मॉड्यूल से बाहर आ जाएगा, इसलिए मुझे वहां बहुत अधिक अंक नहीं दे सकते हैं!
अन्य समाधान जो मैं रास्ते में आया था:
res = "".join(u[x] + l[x] for x in range(len(u)))
res = "".join(k + l[i] for i, k in enumerate(u))
आप 1 का उपयोग कर सकते हैंiteration_utilities.roundrobin
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
from iteration_utilities import roundrobin
''.join(roundrobin(u, l))
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
या एक ManyIterablesही पैकेज से वर्ग:
from iteration_utilities import ManyIterables
ManyIterables(u, l).roundrobin().as_string()
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
1 यह एक तीसरे पक्ष के पुस्तकालय से है जिसे मैंने लिखा है iteration_utilities:।