पायथन में जोड़ी (वर्तमान, अगला) के रूप में एक सूची दर्ज करें


131

मुझे कभी-कभी "वर्तमान" तत्व और "अगले" तत्व को देखते हुए पायथन में एक सूची बनाने की आवश्यकता होती है। मेरे पास अब तक, कोड के साथ ऐसा किया गया है:

for current, next in zip(the_list, the_list[1:]):
    # Do something

यह काम करता है और वही करता है जो मैं उम्मीद करता हूं, लेकिन क्या एक ही काम करने के लिए एक अधिक मुहावरेदार या कुशल तरीका है?


इस प्रश्न के लिए MizardX उत्तर की जाँच करें । लेकिन मुझे नहीं लगता कि यह समाधान आपकी तुलना में अधिक मुहावरेदार है।
फैबियो डिनिज़

2
Build a Basic Python Iterator पर नज़र डालें ।
mkluwe 16

39
चूँकि किसी और ने इसका उल्लेख नहीं किया है, इसलिए मैं वह आदमी हूँ, और nextइस बात का उपयोग करूँगा कि एक बिल्ट-इन मास्क का उपयोग करें।
प्रेषक

@ प्रेंडरल शायद यह पायथन 2 है ...
क्विंटेक

2
@ thecoder16: nextपायथन 2 में भी एक अंतर्निहित कार्य है।
zondo

जवाबों:


131

इटर्स्टस मॉड्यूल डॉक्स से एक प्रासंगिक उदाहरण यहां दिया गया है :

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

अजगर 2 के लिए, आपको itertools.izipइसके बजाय चाहिए zip:

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

यह कैसे काम करता है:

सबसे पहले, दो समानांतर चलने वाले, aऔर bबनाए गए ( tee()कॉल), दोनों मूल चलने वाले के पहले तत्व की ओर इशारा करते हैं। दूसरा पुनरावृत्त, b1 कदम आगे ( next(b, None)) कॉल को स्थानांतरित किया जाता है । इस बिंदु aपर s0 को bइंगित करता है और s1 को इंगित करता है। दोनों aऔर bमूल इटरेटर स्वतंत्र रूप से पार कर सकते हैं - izip समारोह दो iterators लेता है और वापस आ तत्वों की जोड़ी, एक ही गति से दोनों iterators को आगे बढ़ाने में आता है।

एक चेतावनी: tee()फ़ंक्शन दो पुनरावृत्तियों का उत्पादन करता है जो एक दूसरे से स्वतंत्र रूप से आगे बढ़ सकते हैं, लेकिन यह एक लागत पर आता है। यदि पुनरावृत्तियों में से एक दूसरे से आगे बढ़ता है, तोtee() पुनरावृत्तियों में भस्म तत्वों को स्मृति में रखने की आवश्यकता है जब तक कि दूसरा पुनरावृत्ति उन्हें भी वापस कर देता है (यह मूल पुनरावृत्ति को 'रिवाइंड' नहीं कर सकता)। यहाँ यह कोई फर्क नहीं पड़ता क्योंकि एक पुनरावृत्त दूसरे से केवल 1 कदम आगे है, लेकिन सामान्य तौर पर इस तरह से बहुत सारी मेमोरी का उपयोग करना आसान है।

और चूंकि tee()एक nपैरामीटर लिया जा सकता है, इसका उपयोग दो से अधिक समानांतर चलने वालों के लिए भी किया जा सकता है:

def threes(iterator):
    "s -> (s0,s1,s2), (s1,s2,s3), (s2, s3,4), ..."
    a, b, c = itertools.tee(iterator, 3)
    next(b, None)
    next(c, None)
    next(c, None)
    return zip(a, b, c)

4
उदाहरण कोड महान है ... लेकिन, क्या आप इसके लिए थोड़ा स्पष्टीकरण दे सकते हैं कि यह क्यों काम करता है? जैसे कि "टी ()" और "नेक्स्ट ()" यहाँ क्या कर रहे हैं।
जॉन मूलर

@ जॉन मुल्डर: एक संक्षिप्त सारांश।
राफेल डोवगर्ड

9
zip(ł, ł[1:])बहुत छोटा और
अजगर है

2
@ no @z it: नहीं, यह हर पुनरावृत्ति पर काम नहीं करता है और सूचियों पर उपयोग किए जाने पर एक अनावश्यक प्रतिलिपि बनाता है। कार्यों का उपयोग करना पायथोनिक है।
Ry-

यह फ़ंक्शन funcyमॉड्यूल में लागू किया गया है funcy.pairwise:: funcy.readthedocs.io/en/stable/seqs.html#pairwise
ADR

30

अपना खुद का रोल!

def pairwise(iterable):
    it = iter(iterable)
    a = next(it, None)

    for b in it:
        yield (a, b)
        a = b

1
मुझे जिस चीज की जरूरत थी! क्या यह एक अजगर विधि के रूप में अमर हो गया है, या हमें रोलिंग रखने की आवश्यकता है?
ऊह

1
@uhoh: जहाँ तक मुझे पता है अभी तक नहीं किया है!
Ry-

21

चूंकि the_list[1:]वास्तव में पूरी सूची (इसकी पहली तत्व को छोड़कर) की एक प्रति बनाता है, और zip()जब बुलाया जाता है, तो तुरंत tuples की एक सूची बनाता है, आपकी सूची की कुल तीन प्रतियां बनाई जाती हैं। यदि आपकी सूची बहुत बड़ी है, तो आप पसंद कर सकते हैं

from itertools import izip, islice
for current_item, next_item in izip(the_list, islice(the_list, 1, None)):
    print(current_item, next_item)

जो सूची की नकल नहीं करता है।


3
ध्यान दें कि अजगर में 3.x izip itertools से दबा हुआ है और आपको बिलियन ज़िप का उपयोग करना चाहिए
जेवियर कॉम्बेल

1
वास्तव में, the_list[1:]लगभग पूरी सूची की एक कॉपी के बजाय सिर्फ एक स्लाइस ऑब्जेक्ट नहीं बनाता है - इसलिए ओपी की तकनीक उतनी बेकार नहीं है जितना कि आप इसे ध्वनि बनाते हैं।
मार्टीन्यू

3
मुझे लगता [1:]है कि स्लाइस ऑब्जेक्ट (या संभवतः " 1:") बनाता है , जिसे __slice__सूची में पारित किया जाता है , जो तब केवल चयनित तत्वों से युक्त एक प्रति वापस करता है। एक सूची की नकल करने का एक मुहावरेदार तरीका है l_copy = l[:](जो मुझे बदसूरत और अपठनीय लगता है - पसंद है l_copy = list(l))
dcrosta

4
@dcrosta: कोई __slice__विशेष विधि नहीं है। the_list[1:]के बराबर है the_list[slice(1, None)], जो बदले में के बराबर है list.__getitem__(the_list, slice(1, None))
स्वेन मार्नाच

4
@martineau: द्वारा बनाई गई प्रतिलिपि the_list[1:]केवल एक उथली प्रतिलिपि है, इसलिए इसमें प्रति सूची आइटम में से केवल एक सूचक होता है। अधिक मेमोरी सघन हिस्सा zip()स्वयं है, क्योंकि यह tupleप्रति सूची आइटम में एक उदाहरण की एक सूची बनाएगा , जिनमें से प्रत्येक में दो बिंदुओं के लिए दो आइटम और कुछ अतिरिक्त जानकारी होगी। यह सूची उपभोग की गई मेमोरी की मात्रा का नौ गुना उपभोग करेगी [1:]
स्वेन मार्नाच

19

मैं इसे बाहर रख रहा हूं , मैं बहुत हैरान हूं कि किसी ने भी एनुमरेट () के बारे में नहीं सोचा है।

for (index, thing) in enumerate(the_list):
    if index < len(the_list):
        current, next_ = thing, the_list[index + 1]
        #do something

11
वास्तव में, ifयदि आप स्लाइसिंग का उपयोग करते हैं तो भी इसे हटाया जा सकता है:for (index, thing) in enumerate(the_list[:-1]): current, next_ = thing, the_list[index + 1]
जीवनशैली

2
यह वास्तव में उत्तर होना चाहिए, यह किसी भी अतिरिक्त आयात पर भरोसा नहीं करता है और महान काम करता है।
13 अक्टूबर को jamescampbell

हालांकि, यह गैर-अनुक्रमित पुनरावृत्तियों के लिए काम नहीं करता है, इसलिए यह एक सामान्य समाधान नहीं है।
विम

14

सूचकांक द्वारा Iterating एक ही काम कर सकता है:

#!/usr/bin/python
the_list = [1, 2, 3, 4]
for i in xrange(len(the_list) - 1):
    current_item, next_item = the_list[i], the_list[i + 1]
    print(current_item, next_item)

आउटपुट:

(1, 2)
(2, 3)
(3, 4)

आपका उत्तर वर्तमान और अगले के बजाय अधिक पिछला और वर्तमान था , जैसा कि प्रश्न में है। मैंने शब्दार्थ में सुधार करते हुए एक संपादन किया, ताकि वर्तमान तत्व का सूचकांक हमेशा बना रहे। i
बेंग्ट

1

यह अब 16 मई 2020 तक एक साधारण आयात है

from more_itertools import pairwise
for current, next in pairwise(your_iterable):
  print(f'Current = {current}, next = {nxt}')

अधिक-इटर्टूल के लिए डॉक्स हुड के तहत यह कोड अन्य उत्तरों में वैसा ही है, लेकिन मैं उपलब्ध होने पर आयात को प्राथमिकता देता हूं।

यदि आपके पास पहले से यह स्थापित नहीं है तो: pip install more-itertools

उदाहरण

उदाहरण के लिए यदि आपके पास फ़ाइबोनचैकी अनुक्रम था, तो आप बाद के जोड़े के अनुपात की गणना कर सकते हैं:

from more_itertools import pairwise
fib= [1,1,2,3,5,8,13]
for current, nxt in pairwise(fib):
    ratio=current/nxt
    print(f'Curent = {current}, next = {nxt}, ratio = {ratio} ')

0

एक सूची का उपयोग कर एक सूची से जोड़े

the_list = [1, 2, 3, 4]
pairs = [[the_list[i], the_list[i + 1]] for i in range(len(the_list) - 1)]
for [current_item, next_item] in pairs:
    print(current_item, next_item)

आउटपुट:

(1, 2)
(2, 3)
(3, 4)

0

मुझे आश्चर्य है कि किसी ने भी छोटे, सरल और सबसे महत्वपूर्ण सामान्य समाधान का उल्लेख नहीं किया है :

अजगर 3:

from itertools import islice

def n_wise(iterable, n):
    return zip(*(islice(iterable, i, None) for i in range(n)))

अजगर 2:

from itertools import izip, islice

def n_wise(iterable, n):
    return izip(*(islice(iterable, i, None) for i in xrange(n)))

यह जोड़-तोड़ करके चलने-फिरने के लिए काम करता है n=2, लेकिन अधिक संख्या में संभाल सकता है:

>>> for a, b in n_wise('Hello!', 2):
>>>     print(a, b)
H e
e l
l l
l o
o !

>>> for a, b, c, d in n_wise('Hello World!', 4):
>>>     print(a, b, c, d)
H e l l
e l l o
l l o
l o   W
o   W o
  W o r
W o r l
o r l d
r l d !

-2

एक मूल समाधान:

def neighbors( list ):
  i = 0
  while i + 1 < len( list ):
    yield ( list[ i ], list[ i + 1 ] )
    i += 1

for ( x, y ) in neighbors( list ):
  print( x, y )

-2
code = '0016364ee0942aa7cc04a8189ef3'
# Getting the current and next item
print  [code[idx]+code[idx+1] for idx in range(len(code)-1)]
# Getting the pair
print  [code[idx*2]+code[idx*2+1] for idx in range(len(code)/2)]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.