पायथन में, क्या एक ही लंबाई की दो सूचियों को इंटरलेव करने का एक अच्छा तरीका है?
कहते हैं कि मैं दिया हूँ [1,2,3]
और [10,20,30]
। मैं उन में बदलना चाहते हैं [1,10,2,20,3,30]
।
जवाबों:
प्रश्न पोस्ट करने के बाद, मुझे एहसास हुआ कि मैं बस निम्नलिखित कर सकता हूं:
[val for pair in zip(l1, l2) for val in pair]
कहाँ l1
और l2
दो सूची हैं।
यदि इंटरलेव के लिए एन सूचियां हैं, तो
lists = [l1, l2, ...]
[val for tup in zip(*lists) for val in tup]
izip_longest
को Python2 के लिए और zip_longest
python3 `के लिए [val for pair in itertools.zip_longest(l1, l2) for val in pair]
के साथ परिणाम['a', 'b', 'a', 'b', 'a', 'b', None, 'b', None, 'b', None, 'b']
पायथन> = 2.3 के लिए, विस्तारित स्लाइस सिंटैक्स है :
>>> a = [0, 2, 4, 6, 8]
>>> b = [1, 3, 5, 7, 9]
>>> c = a + b
>>> c[::2] = a
>>> c[1::2] = b
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
c = a + b
बिल्कुल सही लंबाई (इस स्तर पर, इसकी सामग्री महत्वपूर्ण नहीं हैं) की एक नई सूची बनाने के लिए एक सरल तरीके के रूप में लाइन का उपयोग किया जाता है। अगले दो पंक्तियों interleaving के वास्तविक कार्य करते हैं a
और b
: पहले एक के तत्वों प्रदान करती है a
के सभी सम-संख्यांकित अनुक्रमित करने के लिए c
; दूसरा b
सभी विषम संख्याओं के तत्वों को निर्दिष्ट करता है c
।
दिया हुआ
a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
कोड
मान लिया जाये कि समान लंबाई की सूची, आप के साथ एक interleaved सूची प्राप्त कर सकते हैं itertools.chain
और zip
:
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
वैकल्पिक
आम तौर पर असमान सूचियों के साथ, उपयोग zip_longest
(अनुशंसित):
[x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
# [1, 100, 2, 200, 3, 300, 999]
कई सूचियाँ सुरक्षित रूप से इंटरलेय की जा सकती हैं:
[x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
# [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
एक पुस्तकालय जो roundrobin
इटर्टूलस नुस्खा के साथ जहाज करता है , interleave
और interleave_longest
।
import more_itertools
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave_longest(a, c))
# [1, 100, 2, 200, 3, 300, 999]
yield from
अंत में, पायथन 3 में कुछ दिलचस्प के लिए (हालांकि अनुशंसित नहीं):
list(filter(None, ((yield from x) for x in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
list([(yield from x) for x in zip(a, b)])
# [1, 10, 2, 20, 3, 30]
+ का उपयोग कर स्थापित करेंpip install more_itertools
मुझे विभिन्न आकारों की सूचियों के साथ ऐसा करने की आवश्यकता थी, जो स्वीकृत उत्तर को संबोधित नहीं करता है।
मेरा समाधान जनरेटर का उपयोग करता है और इसका उपयोग इसकी वजह से थोड़ा अच्छा लगता है:
def interleave(l1, l2):
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 is not None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 is not None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 is None and iter2 is None:
raise StopIteration()
और इसका उपयोग:
>>> a = [1, 2, 3, 4, 5]
>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(interleave(a, b))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'f', 'g']
>>> list(interleave(b, a))
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 'g']
roundrobin
से नुस्खा itertools
मॉड्यूल इस की एक अधिक सामान्य विस्तार है।
वैकल्पिक:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> [y for x in map(None,l1,l2) for y in x if y is not None]
[1, 10, 2, 20, 3, 30]
यह काम करता है क्योंकि मानचित्र समानांतर में सूचियों पर काम करता है। यह 2.2 के तहत समान काम करता है । अपने आप से, None
तथाकथित कार्यों के साथ, map
टुपल्स की एक सूची तैयार करता है:
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
तो बस tuples की सूची समतल।
निश्चित रूप से, लाभ map
किसी भी संख्या में सूचियों के लिए काम करेगा और अलग-अलग लंबाई होने पर भी काम करेगा:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> l3=[101,102,103,104]
>>> [y for x in map(None,l1,l2,l3) for y in x if y in not None]
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
if y
0
भी बाहर फ़िल्टर करेगा , if y is not None
कम नाजुक है।
मुझे ऐक्स का घोल सबसे अच्छा लगता है। यहाँ एक और तरीका है जो मुझे लगता है कि मुझे 2.2 में काम करना चाहिए:
>>> x=range(3)
>>> x
[0, 1, 2]
>>> y=range(7,10)
>>> y
[7, 8, 9]
>>> sum(zip(x,y),[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list
>>> sum(map(list,zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
और एक और तरीका:
>>> a=[x,y]
>>> [a[i][j] for j in range(3) for i in (0,1)]
[0, 7, 1, 8, 2, 9]
तथा:
>>> sum((list(i) for i in zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None]
जब तक आपके पास वह नहीं है None
जिसे आप रखना चाहते हैं
"पायथन में एक ही लंबाई की कई सूचियों को इंटरलेव करें" के शीर्षक के उत्तर के लिए, हम @ekhumoro के 2-सूची उत्तर को सामान्य कर सकते हैं। यह स्पष्ट रूप से आवश्यक है कि सूचियां @NPE द्वारा (सुरुचिपूर्ण) समाधान के विपरीत समान लंबाई हैं
import itertools
def interleave(lists):
"""Interleave a list of lists.
:param lists: List of lists; each inner length must be the same length.
:returns: interleaved single list
:rtype: list
"""
if len(set(len(_) for _ in lists)) > 1:
raise ValueError("Lists are not all the same length!")
joint = list(itertools.chain(*lists))
for l_idx, li in enumerate(lists):
joint[l_idx::len(lists)] = li
return joint
उदाहरण:
>>> interleave([[0,2,4], [1, 3, 5]])
[0, 1, 2, 3, 4, 5]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12]])
[0, 1, 10, 2, 3, 11, 4, 5, 12]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14, 15]])
[0, 1, 10, 13, 2, 3, 11, 14, 4, 5, 12, 15]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in interleave
ValueError: Lists are not all the same length!
>>> interleave([[0,2,4]])
[0, 2, 4]
पार्टी के लिए बहुत देर हो चुकी है, और बहुत सारे अच्छे जवाब हैं, लेकिन मैं extend()
विधि का उपयोग करके एक सरल समाधान प्रदान करना चाहूंगा :
list1 = [1, 2, 3]
list2 = [10, 20, 30]
new_list = []
for i in range(len(list1)):
new_list.extend([list1[i], list2[i]])
print(new_list)
आउटपुट:
[1, 10, 2, 20, 3, 30]
it = iter(l1); list((yield next(it)) or i for i in l2)