एक सूची में हर दो तत्वों पर Iterating


209

मैं एक forलूप या सूची समझ कैसे बनाऊं ताकि हर पुनरावृत्ति मुझे दो तत्व प्रदान करे?

l = [1,2,3,4,5,6]

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

आउटपुट:

1+2=3
3+4=7
5+6=11

2
ओवरलैपिंग जोड़ी के लिए: stackoverflow.com/questions/5434891/…
user202729

जवाबों:


231

आपको एक pairwise()(या grouped()) कार्यान्वयन की आवश्यकता है।

पायथन 2 के लिए:

from itertools import izip

def pairwise(iterable):
    "s -> (s0, s1), (s2, s3), (s4, s5), ..."
    a = iter(iterable)
    return izip(a, a)

for x, y in pairwise(l):
   print "%d + %d = %d" % (x, y, x + y)

या, आम तौर पर:

from itertools import izip

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return izip(*[iter(iterable)]*n)

for x, y in grouped(l, 2):
   print "%d + %d = %d" % (x, y, x + y)

पायथन 3 में, आप izipअंतर्निहित zip()फ़ंक्शन के साथ प्रतिस्थापित कर सकते हैं और ड्रॉप कर सकते हैं import

करने के लिए सभी क्रेडिट मार्टिन्यू के लिए अपने जवाब के लिए मेरे सवाल है, मैं इस पाया है, क्योंकि यह केवल सूची पर एक बार iterates और इस प्रक्रिया में किसी भी अनावश्यक सूचियों का निर्माण नहीं करता बहुत ही कुशल होने के लिए।

नायब : यह अजगर के स्वयं के दस्तावेज में pairwiseनुस्खा के साथ भ्रमित नहीं होना चाहिए , जो पैदावार करता है , जैसा कि @lazyr द्वारा टिप्पणियों में बताया गया है ।itertoolss -> (s0, s1), (s1, s2), (s2, s3), ...

उन लोगों के लिए थोड़ा अतिरिक्त जो पायथन 3 पर मैपी के साथ टाइप चेकिंग करना चाहते हैं :

from typing import Iterable, Tuple, TypeVar

T = TypeVar("T")

def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
    """s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
    return zip(*[iter(iterable)] * n)

16
इटर्स्टूलस रेसिपी सेक्शन में दिए गए जोड़ी वाइज फंक्शन से भ्रमित न हों , जो कि पैदावार करता हैs -> (s0,s1), (s1,s2), (s2, s3), ...
लॉरिट्ज वी। थुलो

1
यह एक अलग बात करता है। आपका संस्करण केवल itertoolsउसी नाम के साथ रेसिपी फ़ंक्शन की तुलना में जोड़े की आधी संख्या देता है । बेशक आपका तेज है ...
स्वेन मार्नाच

है ना? आपका कार्य और समारोह मैंने अलग-अलग काम करने के लिए संदर्भित किया, और यह मेरी टिप्पणी का बिंदु था।
लॉरिट्ज़ वी। थुलोव

5
सावधान रहे! इन फ़ंक्शंस का उपयोग करने से आपको पुनरावृति के अंतिम तत्वों पर पुनरावृत्ति नहीं होने का खतरा होता है। उदाहरण: सूची (समूहीकृत ([१,२,३], २)) >>> [(१, २)] .. जब आप अपेक्षा करेंगे (१,२), (३,)]
उदाफनी

4
@ एरिक 49: प्रश्न में निर्दिष्ट मामले में, 'अधूरा' टपल होने का कोई मतलब नहीं होगा। यदि आप एक अधूरा टपल शामिल करना चाहते हैं, तो आप izip_longest()इसके बजाय उपयोग कर सकते हैं izip()। जैसे: list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0))-> [(1, 2), (3, 0)]। उम्मीद है की यह मदद करेगा।
जॉन्सिवेब

191

वैसे आपको 2 तत्वों का टपल चाहिए

data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
    print str(i), '+', str(k), '=', str(i+k)

कहाँ पे:

  • data[0::2] का मतलब है कि तत्वों का सबसेट संग्रह बनाना (index % 2 == 0)
  • zip(x,y) x और y समान अनुक्रमणिका तत्वों से टपल संग्रह बनाता है।

8
इसे दो से अधिक तत्वों की आवश्यकता होने पर भी बढ़ाया जा सकता है। उदाहरण के लिएfor i, j, k in zip(data[0::3], data[1::3], data[2::3]):
जीवनशैली

19
एक आयात में खींचने और एक फ़ंक्शन को परिभाषित करने की तुलना में बहुत क्लीनर!
किमी '20:19

7
@kmarsh: लेकिन यह केवल दृश्यों पर काम करता है, फ़ंक्शन किसी भी चलने योग्य पर काम करता है; और यह O (N) अतिरिक्त स्थान का उपयोग करता है, फ़ंक्शन नहीं करता है; दूसरी ओर, यह आम तौर पर तेज होता है। एक या दूसरे को लेने के अच्छे कारण हैं; डरना importउनमें से एक नहीं है।
दोपहर

77
>>> l = [1,2,3,4,5,6]

>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]

>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]

>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']

1
यह पायथन -३.६.० पर काम नहीं कर रहा है, लेकिन फिर भी पायथन -२.०.१० पर काम कर रहा है
हामिद रोहानी

6
@ HamidRohani Python 3 में zipएक zipऑब्जेक्ट देता है , जो सब्स्क्रिप्टेबल नहीं है। इसे पहले एक अनुक्रम ( listऔर tuple, आदि) में परिवर्तित करने की आवश्यकता है , लेकिन "काम नहीं करना" थोड़ा खिंचाव है।
तिजोरी

58

एक सरल उपाय।

l = [१, २, ३, ४, ५, ६]

मैं सीमा में (0, len (l), 2):
    प्रिंट str (l [i]), '+', str (l [i + 1]), '=', str (l [i] + l [i + 1])

1
क्या होगा अगर आपकी सूची भी नहीं है, और आप बस अंतिम संख्या दिखाना चाहते हैं जैसा कि यह है?
हंस डी जोंग

@HansdeJong आपको नहीं मिला। कृपया थोड़ा और समझाएं।
टास्किनॉर

2
धन्यवाद। मुझे पहले ही पता चल गया था कि यह कैसे करना है। समस्या यह थी कि यदि आपके पास एक सूची थी, जिसमें संख्याओं की संख्या भी नहीं थी, तो उसे एक इंडेक्स त्रुटि मिलेगी। इसे एक कोशिश के साथ हल किया: सिवाय:
हंस डी जोंग

या ((l[i], l[i+1])for i in range(0, len(l), 2))जनरेटर के लिए, आसानी से लंबे समय तक ट्यूपल्स के लिए संशोधित किया जा सकता है।
बेसल शिशानी

44

हालांकि उपयोग करने वाले सभी उत्तर zipसही हैं, मुझे लगता है कि कार्यक्षमता को लागू करने से खुद को अधिक पठनीय कोड की ओर जाता है:

def pairwise(it):
    it = iter(it)
    while True:
        try:
            yield next(it), next(it)
        except StopIteration:
            # no more elements in the iterator
            return

it = iter(it)हिस्सा सुनिश्चित है कि itवास्तव में एक इटरेटर, न सिर्फ एक iterable है। यदि itपहले से ही एक पुनरावृत्त है, तो यह पंक्ति एक सेशन नहीं है।

उपयोग:

for a, b in pairwise([0, 1, 2, 3, 4, 5]):
    print(a + b)

2
यह समाधान
टुपल्स के

1
यह समाधान भी काम करता है यदि itकेवल एक पुनरावृत्ति है और एक चलने योग्य नहीं है। अन्य समाधान अनुक्रम के लिए दो स्वतंत्र पुनरावृत्तियों को बनाने की संभावना पर भरोसा करते हैं।
आसमान छू रहा है

मुझे यह उत्तर देखने से पहले stackoverflow.com/a/16815056/2480481 पर यह दृष्टिकोण मिला । क्लीनर, ज़िप से निपटने की तुलना में आसान है ()।
m3nda

2
मुझे पसंद है कि यह स्वीकृत उत्तर के रूप में ट्रिपलिंग मेमोरी के उपयोग से बचने की अनुमति देता है।
केंटजो

यह PEP 479 केfor कारण Python 3.5+ में छोरों के साथ अच्छी तरह से काम नहीं करता है , जो जनरेटर के साथ उठाए गए किसी भी स्थान को बदलता है । StopIterationRuntimeError
सिडनी


18

यदि आप प्रदर्शन में रुचि रखते हैं, तो मैंने simple_benchmarkसमाधानों के प्रदर्शन की तुलना करने के लिए एक छोटा बेंचमार्क (मेरी लाइब्रेरी का उपयोग ) किया और मैंने अपने पैकेज में से एक फ़ंक्शन शामिल किया:iteration_utilities.grouper

from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder

bench = BenchmarkBuilder()

@bench.add_function()
def Johnsyweb(l):
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return zip(a, a)

    for x, y in pairwise(l):
        pass

@bench.add_function()
def Margus(data):
    for i, k in zip(data[0::2], data[1::2]):
        pass

@bench.add_function()
def pyanon(l):
    list(zip(l,l[1:]))[::2]

@bench.add_function()
def taskinoor(l):
    for i in range(0, len(l), 2):
        l[i], l[i+1]

@bench.add_function()
def mic_e(it):
    def pairwise(it):
        it = iter(it)
        while True:
            try:
                yield next(it), next(it)
            except StopIteration:
                return

    for a, b in pairwise(it):
        pass

@bench.add_function()
def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)

यहां छवि विवरण दर्ज करें

इसलिए यदि आप बाहरी निर्भरता के बिना सबसे तेज़ समाधान चाहते हैं, तो आपको शायद जॉनीस्वेब द्वारा दिए गए दृष्टिकोण का उपयोग करना चाहिए (लेखन के समय यह सबसे उत्कीर्ण और स्वीकृत उत्तर है)।

आप अतिरिक्त निर्भरता कोई आपत्ति नहीं है तो grouperसे iteration_utilitiesशायद थोड़ा तेजी से हो जाएगा।

अतिरिक्त विचार

कुछ दृष्टिकोणों में कुछ प्रतिबंध हैं, जिनकी चर्चा यहाँ नहीं की गई है।

उदाहरण के लिए कुछ समाधान केवल अनुक्रमों के लिए काम करते हैं (यानी सूची, तार आदि), उदाहरण के लिए मार्गस / प्यानोन / टास्किनोर समाधान, जो इंडेक्सिंग का उपयोग करता है, जबकि अन्य समाधान किसी भी चलने योग्य (जो अनुक्रम और जनरेटर, पुनरावृत्तियों) पर काम करते हैं , जैसे जॉनीस्वेब / mic_e / मेरे समाधान।

तब जॉनीस्वेब ने एक समाधान भी दिया जो अन्य आकारों के लिए 2 की तुलना में काम करता है जबकि अन्य उत्तर नहीं देते हैं (ठीक है, iteration_utilities.grouperतत्वों की संख्या "समूह" पर सेट करने की भी अनुमति देता है)।

फिर यह भी सवाल है कि सूची में विषम संख्या में तत्व होने पर क्या होना चाहिए। क्या शेष वस्तु को खारिज कर दिया जाना चाहिए? क्या सूची को आकार देने के लिए पैड किया जाना चाहिए? क्या शेष वस्तु को एकल के रूप में लौटाया जाना चाहिए? अन्य उत्तर इस बिंदु को सीधे संबोधित नहीं करते हैं, हालांकि अगर मैंने कुछ भी अनदेखा नहीं किया है, तो वे सभी इस दृष्टिकोण का पालन करते हैं कि शेष आइटम को खारिज कर दिया जाना चाहिए (टास्किनर्स उत्तर को छोड़कर - जो वास्तव में अपवाद पैदा करेगा)।

साथ grouperआप तय कर सकते हैं कि आप क्या करना चाहते हैं:

>>> from iteration_utilities import grouper

>>> list(grouper([1, 2, 3], 2))  # as single
[(1, 2), (3,)]

>>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
[(1, 2)]

>>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
[(1, 2), (3, None)]

12

एक साथ कमांड zipऔर प्रयोग करें iter:

मुझे लगता है कि यह समाधान iterकाफी सुरुचिपूर्ण है:

it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]

जो मुझे पायथन 3 ज़िप प्रलेखन में मिला ।

it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')

# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11

Nएक समय में तत्वों को सामान्य करने के लिए :

N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]

10
for (i, k) in zip(l[::2], l[1::2]):
    print i, "+", k, "=", i+k

zip(*iterable) प्रत्येक पुनरावृत्ति के अगले तत्व के साथ एक टपल देता है।

l[::2] सूची का पहला, तीसरा, 5 वां इत्यादि तत्व देता है: पहला कोलन इंगित करता है कि स्लाइस शुरुआत में शुरू होता है क्योंकि इसके पीछे कोई संख्या नहीं होती है, दूसरे कोलन की जरूरत तभी होती है जब आप स्लाइस में 'स्टेप' चाहते हैं। '(इस मामले में 2)।

l[1::2]एक ही बात करता है, लेकिन सूची के दूसरे तत्व में शुरू होता है इसलिए यह मूल सूची के 2, 4, 6, आदि तत्व को वापस करता है ।


4
यह जवाब मार्गस ने दो साल पहले ही दे दिया था। stackoverflow.com/questions/5389507/…
कैबबुंगा

1
1 यह समझाने के लिए कि [number::number]वाक्य रचना कैसे काम करती है। जो अक्सर अजगर का उपयोग नहीं करता है के लिए मददगार
Alby

2

अनपैकिंग के साथ:

l = [1,2,3,4,5,6]
while l:
    i, k, *l = l
    print(str(i), '+', str(k), '=', str(i+k))

वाह! मैं इस बारे में क्यों नहीं सोच सकता था :) आपको ऐसे मामले को संभालने की ज़रूरत है जहाँ कोई पूर्ण जोड़ी (विषम प्रविष्टियाँ) नहीं हैं
सौरव कुमार

1

किसी के लिए भी यह मदद कर सकता है, यहां एक समान समस्या का समाधान है लेकिन अतिव्यापी जोड़े (पारस्परिक रूप से अनन्य जोड़े के बजाय)।

पायथन इटर्टूलस प्रलेखन से :

from itertools import izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

या, आम तौर पर:

from itertools import izip

def groupwise(iterable, n=2):
    "s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
    t = tee(iterable, n)
    for i in range(1, n):
        for j in range(0, i):
            next(t[i], None)
    return izip(*t)


1

मुझे एक सूची को एक संख्या से विभाजित करने और इस तरह तय करने की आवश्यकता है।

l = [1,2,3,4,5,6]

def divideByN(data, n):
        return [data[i*n : (i+1)*n] for i in range(len(data)//n)]  

>>> print(divideByN(l,2))
[[1, 2], [3, 4], [5, 6]]

>>> print(divideByN(l,3))
[[1, 2, 3], [4, 5, 6]]

1

ऐसा करने के कई तरीके हैं। उदाहरण के लिए:

lst = [1,2,3,4,5,6]
[(lst[i], lst[i+1]) for i,_ in enumerate(lst[:-1])]    
>>>[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

[i for i in zip(*[iter(lst)]*2)]    
>>>[(1, 2), (3, 4), (5, 6)]

0

सोचा कि यह n> 2 के लिए मेरे सामान्यीकरण को साझा करने के लिए एक अच्छी जगह है, जो सिर्फ एक पुनरावृत्ति खिड़की पर है:

def sliding_window(iterable, n):
    its = [ itertools.islice(iter, i, None) 
            for i, iter
            in enumerate(itertools.tee(iterable, n)) ]                               

    return itertools.izip(*its)

0

इस प्रश्न का शीर्षक भ्रामक है, आप लगातार जोड़े की तलाश में रहते हैं, लेकिन यदि आप सभी संभावित जोड़ों के सेट पर पुनरावृति करना चाहते हैं, तो यह काम करेगा:

for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:

0

टाइपिंग का उपयोग करके आप mypy स्थैतिक विश्लेषण उपकरण का उपयोग करके डेटा सत्यापित कर सकते हैं :

from typing import Iterator, Any, Iterable, TypeVar, Tuple

T_ = TypeVar('T_')
Pairs_Iter = Iterator[Tuple[T_, T_]]

def legs(iterable: Iterator[T_]) -> Pairs_Iter:
    begin = next(iterable)
    for end in iterable:
        yield begin, end
        begin = end

0

एक सरलीकृत दृष्टिकोण:

[(a[i],a[i+1]) for i in range(0,len(a),2)]

यह उपयोगी है यदि आपकी सरणी एक है और आप जोड़े द्वारा उस पर पुनरावृति करना चाहते हैं। उदाहरण के लिए, ट्रिपल या अधिक पर "श्रेणी" चरण कमांड को बदलने के लिए:

[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]

(यदि आपके सरणी की लंबाई और चरण फिट नहीं है, तो आपको अतिरिक्त मूल्यों से निपटना होगा)


-1

यहां हमारे पास वह alt_elemविधि हो सकती है जो आपके लूप के लिए फिट हो सकती है।

def alt_elem(list, index=2):
    for i, elem in enumerate(list, start=1):
        if not i % index:
           yield tuple(list[i-index:i])


a = range(10)
for index in [2, 3, 4]:
    print("With index: {0}".format(index))
    for i in alt_elem(a, index):
       print(i)

आउटपुट:

With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)

नोट: ऊपर दिए गए समाधान कुशल नहीं हो सकते हैं, यह मानते हुए कि फंक में किए गए कार्यों पर विचार नहीं किया जाएगा।


-1
a_list = [1,2,3,4,5,6]
empty_list = [] 
for i in range(0,len(a_list),2):
   empty_list.append(a_list[i]+a_list[i+1])   
print(empty_list)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.