पायथन में एक ही लंबाई के कई सूचियों को इंटरलेव करें


85

पायथन में, क्या एक ही लंबाई की दो सूचियों को इंटरलेव करने का एक अच्छा तरीका है?

कहते हैं कि मैं दिया हूँ [1,2,3]और [10,20,30]। मैं उन में बदलना चाहते हैं [1,10,2,20,3,30]


अनुशंसित नहीं है, लेकिन यह प्रयास करें:it = iter(l1); list((yield next(it)) or i for i in l2)
क्रिस_रैंड

जवाबों:


112

प्रश्न पोस्ट करने के बाद, मुझे एहसास हुआ कि मैं बस निम्नलिखित कर सकता हूं:

[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]

5
केवल तभी काम करता है जब l1 और l2 में तत्वों की समान संख्या हो
Emmanuel

14
@ इमानुएल: सवाल यह है कि "पायथन में, एक ही लंबाई की दो सूचियों को इंटरलेव करने का एक अच्छा तरीका है ?"
NPE

1
आप सबसे लंबे समय तक सूची, उपयोग करने के लिए पैड करना चाहते हैं तो izip_longestको Python2 के लिए और zip_longestpython3 `के लिए [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']
सेर्गेई ज़ाराखोव

71

पायथन> = 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


25

दिया हुआ

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]

वैकल्पिक

itertools.zip_longest

आम तौर पर असमान सूचियों के साथ, उपयोग 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]

more_itertools+

एक पुस्तकालय जो 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


8

मुझे विभिन्न आकारों की सूचियों के साथ ऐसा करने की आवश्यकता थी, जो स्वीकृत उत्तर को संबोधित नहीं करता है।

मेरा समाधान जनरेटर का उपयोग करता है और इसका उपयोग इसकी वजह से थोड़ा अच्छा लगता है:

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मॉड्यूल इस की एक अधिक सामान्य विस्तार है।
शैडो रेंजर

7

वैकल्पिक:

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

1
if y0भी बाहर फ़िल्टर करेगा , if y is not Noneकम नाजुक है।
जोहान रिट्जेल

@ जोकेन रिट्जेल: धन्यवाद! मैं आपसे सहमत हुँ। फिक्स्ड। मैंने इसे केवल मांसपेशियों के साथ लिखा ...
को भेड़िया

3

मुझे ऐक्स का घोल सबसे अच्छा लगता है। यहाँ एक और तरीका है जो मुझे लगता है कि मुझे 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]

0
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None]

जब तक आपके पास वह नहीं है Noneजिसे आप रखना चाहते हैं


0

"पायथन में एक ही लंबाई की कई सूचियों को इंटरलेव करें" के शीर्षक के उत्तर के लिए, हम @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]

0

पार्टी के लिए बहुत देर हो चुकी है, और बहुत सारे अच्छे जवाब हैं, लेकिन मैं 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]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.