দুটি স্ট্রিং ইন্টারলেভ করার বেশিরভাগ অজগর উপায়


115

দুটি স্ট্রিং একসাথে জাল করার সর্বাধিক অজগর উপায় কী?

উদাহরণ স্বরূপ:

ইনপুট:

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

আউটপুট:

'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

2
এখানে উত্তরগুলি মূলত ধরে নিয়েছে যে আপনার দুটি ইনপুট স্ট্রিং একই দৈর্ঘ্যের হবে। এটি কি নিরাপদ অনুমান বা আপনার পরিচালনা করা দরকার?
সুপারবিসাইডম্যান

@ সুপারবাইজডম্যান আপনার যদি কোনও সমাধান থাকে তবে সমস্ত শর্ত কীভাবে পরিচালনা করবেন তা দেখতে সহায়ক হতে পারে। এটি প্রশ্নের সাথে সম্পর্কিত, তবে আমার ক্ষেত্রে বিশেষভাবে নয়।
ব্র্যান্ডন ডিও

3
@drexx শীর্ষ উত্তরদাতা যেভাবেই হোক এর জন্য একটি সমাধানের সাথে মন্তব্য করেছিলেন, তাই আমি কেবল তাদের পোস্টে এটি সম্পাদনা করেছি যাতে এটি ব্যাপক।
সুপারবিসাইডম্যান

উত্তর:


127

আমার জন্য, সর্বাধিক পাইথোনিক * উপায়টি হ'ল নিম্নলিখিতটি যা একই কাজটি করে তবে +প্রতিটি স্ট্রিংয়ের পৃথক চরিত্রগুলিকে একত্রিত করার জন্য অপারেটরটি ব্যবহার করে :

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কমপক্ষে আমার চোখের জন্য আরও সহজেই দৃশ্যমানভাবে পার্স করা হয়েছে।


1
এন স্ট্রিংগুলির কোডিং প্রচেষ্টা হ'ল ও (এন), যদিও। তবুও, এন যতক্ষণ ছোট হয় ততক্ষণ ভাল।
টাইগারহকটি 3

আপনার জেনারেটর সম্ভবত যোগদানের চেয়ে বেশি ওভারহেডের কারণ করছে।
প্যাডেরিক কানিংহাম

5
রান করুন "".join([i + j for i, j in zip(l1, l2)])এবং এটি অবশ্যই দ্রুততম হবে
প্যাডেরিক কানিংহাম

6
"".join(map("".join, zip(l1, l2)))আরও দ্রুত, যদিও অগত্যা আরও অজগর নয়।
আলেক্সি তোড়হামো

63

দ্রুত বিকল্প

অন্য উপায়:

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

পাইথন ৩.৩.২।

বিভিন্ন দৈর্ঘ্যের স্ট্রিংগুলির জন্য পার্থক্য

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

49

সাথে join()এবং zip()

>>> ''.join(''.join(item) for item in zip(u,l))
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

17
বা''.join(itertools.chain.from_iterable(zip(u, l)))
ব্লেন্ডার

1
zipসংক্ষিপ্ত তালিকাটি সম্পূর্ণরূপে পুনরাবৃত্তি হওয়ার পরে যখন থামাগুলি থামবে তখন এটি অন্যের চেয়ে ছোট হলে এটি একটি তালিকা কেটে যাবে ।
সুপারবিসাইডম্যান

5
নিবন্ধন করুন itertools.zip_longestএটি কোনও সমস্যা হয়ে থাকলে ব্যবহার করা যেতে পারে।
টাইগারহকটি 3

18

পাইথন 2 দ্বারা পর্যন্ত দ্রুত উপায় জিনিস, ছোট স্ট্রিং জন্য তালিকা slicing এবং ~ দীর্ঘ বেশী জন্য 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")

ছোট ধরণের সাধারণ ক্ষেত্রে বিশেষ কেসিং সাহায্য করবে। এফডাব্লুআইডাব্লু, এটি কেবল দীর্ঘ স্ট্রিংয়ের জন্য তালিকার তালিকার গতি এবং ছোট স্ট্রিংয়ের জন্য 4 থেকে 5 ধীর গতির ফ্যাক্টর 3x

যে কোনও উপায়ে আমি joinসমাধানগুলি পছন্দ করি তবে সময়গুলির উল্লেখ অন্য কোথাও উল্লেখ করার পরে আমি ভেবেছিলাম আমিও এতে যোগ দিতে পারি।


16

আপনি যদি দ্রুততম উপায় চান, আপনি এরেরটুলগুলি এর সাথে সংযুক্ত করতে পারেন 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

তবে পাইথন 2 এর জন্য, ভিড্রাকের পরামর্শ এখন পর্যন্ত সবচেয়ে দ্রুত:

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

2
কেন list?? অপ্রয়োজনীয়
কপারফিল্ড

1
আমার পরীক্ষাগুলি অনুসারে নয়, আপনি মধ্যস্থতাকারী তালিকা তৈরি করতে সময় হারাবেন এবং এটি পুনরাবৃত্তিকারীদের ব্যবহারের উদ্দেশ্যকে পরাজিত করবে। Timeit "".join(list(...))আমাকে 6,715280318699769 দিতে এবং timeit "".join(starmap(...))আমাকে 6,46332361384313 দিতে
কপারফিল্ড

1
তাহলে কি, যন্ত্র নির্ভর? কারণ যেখানেই আমি পরীক্ষাটি চালাই না কেন আমি একই সঠিক ফলাফলটি পাই তার "".join(list(starmap(add, izip(l1,l2))))চেয়ে ধীর "".join(starmap(add, izip(l1,l2)))। আমি আমার মেশিনটিতে পাইথন ২.7.১১ এবং পাইথন 3.5.৩.১ তে অজগর py.৪.৩ সহ www.python.org এর ভার্চুয়াল কনসোলে পরীক্ষা চালিয়েছি এবং সবাই একই কথা বলেছি এবং আমি এটি কয়েকবার চালিয়েছি এবং সর্বদা একই
কপারফিল্ড

আমি পড়েছি এবং আমি যা দেখতে পাচ্ছি তা হ'ল এটি আপনার বাফার ভেরিয়েবলের অভ্যন্তরে অভ্যন্তরীণভাবে একটি তালিকা তৈরি করে আপনি তার কাছে যা যা পাস তা নির্বিশেষে, তাই কোনও কারণেই এটি একটি তালিকা দেবেন না
কপারফিল্ড

@ কপারফিল্ড, আপনি কি তালিকার কল সম্পর্কে কথা বলছেন বা একটি তালিকা পাস করছেন?
প্যাডেরিক কানিংহাম

12

আপনি এটি ব্যবহার করেও করতে পারেন mapএবং operator.add:

from operator import add

u = 'AAAAA'
l = 'aaaaa'

s = "".join(map(add, u, l))

আউটপুট :

'AaAaAaAaAa'

মানচিত্রটি যা করে তা হ'ল এটি uপ্রথম উপাদান এবং দ্বিতীয় পুনরাবৃত্ত থেকে প্রথম উপাদান থেকে প্রতিটি উপাদান নেয় lএবং প্রথম যুক্তি হিসাবে সরবরাহিত ফাংশনটি প্রয়োগ করে add। তারপরে যোগ দিন শুধু তাদের সাথে যোগ দিন।


9

জিমের উত্তর দুর্দান্ত, তবে আপনি কয়েকটি আমদানিতে আপত্তি না দেখলে এখানে আমার প্রিয় বিকল্পটি রয়েছে:

from functools import reduce
from operator import add

reduce(add, map(add, u, l))

7
তিনি বেশিরভাগ পাইথোনিক বলেছেন, বেশিরভাগ হাস্কেলিক নয়;)
কার্ট

7

এই পরামর্শগুলির অনেকগুলি স্ট্রিংগুলি সমান দৈর্ঘ্যের বলে ধরে নেয়। সম্ভবত এটি সমস্ত যুক্তিসঙ্গত ব্যবহারের কেসগুলি কভার করে, তবে কমপক্ষে আমার কাছে মনে হয় আপনি পৃথক দৈর্ঘ্যের স্ট্রিংগুলিও সামঞ্জস্য করতে চাইতে পারেন। বা আমিই কেবল সেই ভাবছি যে জালটি কিছুটা এভাবে কাজ করা উচিত:

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:]])

5

আমি দুটি ব্যবহার করতে চাই for, ভেরিয়েবলের নামগুলি যা চলছে তার জন্য একটি ইঙ্গিত / অনুস্মারক দিতে পারে:

"".join(char for pair in zip(u,l) for char in pair)

4

কেবলমাত্র আরও একটি বেসিক পদ্ধতির যোগ করতে:

st = ""
for char in u:
    st = "{0}{1}{2}".format( st, char, l[ u.index( char ) ] )

4

ও (1) প্রয়াসের সাহায্যে এন স্ট্রিং পরিচালনা করতে, এখানে ডাবল-তালিকা-বোধগম্য উত্তরটি বিবেচনা না করার জন্য কিছুটা অ-অজগরকে মনে হচ্ছে:

"".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

এখনও দ্রুততম উত্তরের মতো দ্রুত নয়, যদিও: যা এই একই ডেটা এবং কম্পিউটারে 50.3 এমএস পেয়েছে
6:38

3

বর্তমানের শীর্ষস্থানীয় সমাধানের চেয়ে সম্ভবত দ্রুত এবং খাটো:

from itertools import chain

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

res = "".join(chain(*zip(u, l)))

কৌশল গতি অনুসারে যতটা সম্ভব সি-পর্যায়ে করা সম্ভব। অসম স্ট্রিংগুলির জন্য একই জিপ_লনটেস্ট () ঠিক করুন এবং এটি চেইনের মতো একই মডিউল থেকে বেরিয়ে আসবে () সুতরাং সেখানে আমাকে খুব বেশি পয়েন্ট ডাইং করতে পারবেন না!

পথে অন্যান্য সমাধান আমি নিয়ে এসেছি:

res = "".join(u[x] + l[x] for x in range(len(u)))

res = "".join(k + l[i] for i, k in enumerate(u))

3

আপনি 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


2

আমি পঠনযোগ্য এবং সহজ উপায় পেতে জিপ () ব্যবহার করব:

result = ''
for cha, chb in zip(u, l):
    result += '%s%s' % (cha, chb)

print result
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.