পাইথনে জোড় (বর্তমান, পরের) হিসাবে একটি তালিকা পরিবেশন করুন


131

আমার মাঝে মাঝে পাইথনের একটি তালিকা "বর্তমান" উপাদান এবং "পরবর্তী" উপাদানটির দিকে তাকানো দরকার। আমি এখনও অবধি কোড সহ এমনটি করেছি:

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

এটি কাজ করে এবং আমি যা প্রত্যাশা করি তা করে, তবে একই জিনিসটি করার মতো আরও কোনও মুশকিল বা কার্যকর উপায় আছে কি?


এই প্রশ্নের জন্য MizardX উত্তর চেক করুন । তবে আমি মনে করি না যে এই সমাধানটি আপনার চেয়ে মূ .়।
ফ্যাবিও ডিনিজ


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)কল) সরানো হয় । এই মুহূর্তে as0 এবং bপয়েন্ট s1। উভয়ই aএবং bমূল পুনরুক্তি স্বাধীনভাবে অতিক্রম করতে পারে - izip ফাংশন দুটি পুনরুক্তি নেয় এবং একই গতিতে উভয় পুনরুক্তিকে অগ্রসর করে ফিরে আসা উপাদানগুলির জোড়া তৈরি করে।

একটি সতর্কতা: 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
@ নোজি: না, এটি প্রতিটি পুনরাবৃত্তির উপরে কাজ করে না এবং তালিকাগুলিতে ব্যবহার করার সময় একটি অপ্রয়োজনীয় অনুলিপি তৈরি করে। ফাংশন ব্যবহার করা পাইথোনিক।
রাই-

এই ফাংশনটি funcyমডিউলটিতে প্রয়োগ করা হয়েছে funcy.pairwise:: funcy.readthedocs.io/en/stable/seqs.html# জোড়ায়
এডিআর

30

নিজের রোল!

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

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

1
ঠিক যেটা আমার দরকার ছিল! এটি কি অজগর পদ্ধতি হিসাবে অমর হয়ে গেছে বা আমাদের ঘূর্ণায়মান হওয়া দরকার?
উহো

1
@ উহোহ: এখনও পর্যন্ত আমি জানি না!
রাই-

21

যেহেতু the_list[1:]প্রকৃতপক্ষে পুরো তালিকার একটি অনুলিপি তৈরি করা হয়েছে (এর প্রথম উপাদানটি বাদে) এবং zip()তাত্ক্ষণিকভাবে ডেকে পাঠানো তালিকার তালিকা তৈরি করে, আপনার তালিকার মোট তিনটি অনুলিপি তৈরি করা হয়েছে। যদি আপনার তালিকাটি খুব বড় হয় তবে আপনি পছন্দ করতে পারেন

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
দ্রষ্টব্য যে পাইথন x.x আইজিপ ইটারটোলগুলি দমন করে এবং আপনার বিল্টিন জিপ ব্যবহার করা উচিত
জেভিয়ার কমবেল

1
প্রকৃতপক্ষে, the_list[1:]প্রায় পুরো তালিকার অনুলিপি চেয়ে কেবল কোনও স্লাইস অবজেক্ট তৈরি করে না - সুতরাং ওপির কৌশলটি যেমন আপনি শব্দ করেন তেমন অপব্যয় হয় না।
মার্টিনিউ

3
আমি মনে করি [1:]স্লাইস অবজেক্ট (বা সম্ভবত " 1:") তৈরি করে, যা __slice__তালিকায় দেওয়া হয়, যা কেবলমাত্র নির্বাচিত উপাদানগুলির সাথে একটি অনুলিপি প্রদান করে। একটি তালিকা অনুলিপি করার একটি অহঙ্কারী উপায় হ'ল l_copy = l[:](যা আমি l_copy = list(l)
কুরুচিপূর্ণ

4
@ ডিক্রোস্টা: কোনও __slice__বিশেষ পদ্ধতি নেই। the_list[1:]সমতূল্য the_list[slice(1, None)], যেটা ঘুরে ফিরে সমতূল্য list.__getitem__(the_list, slice(1, None))
সোভেন মারনাচ

4
@ মার্টিনো: তৈরি করা অনুলিপিটি the_list[1:]কেবল একটি অগভীর অনুলিপি, সুতরাং এতে প্রতি তালিকা আইটেমের মধ্যে কেবল একটি পয়েন্টার থাকে। আরও মেমরি নিবিড় অংশটি zip()নিজেই, কারণ এটি tupleপ্রতি তালিকা আইটেমের মধ্যে একটি উদাহরণের একটি তালিকা তৈরি করবে , যার প্রতিটিতে দুটি আইটেমের জন্য দুটি পয়েন্টার এবং কিছু অতিরিক্ত তথ্য থাকবে। এই তালিকাটি [1:]গ্রাহকদের দ্বারা কপি করা মেমরির পরিমাণ থেকে নয়গুণ বেশি খরচ করবে consume
সোভেন মারনাচ

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
এটি সত্যই উত্তর হওয়া উচিত, এটি কোনও অতিরিক্ত আমদানির উপর নির্ভর করে না এবং দুর্দান্ত কাজ করে।
jamescampbell

যদিও এটি অ-সূচকযোগ্য পুনরাবৃত্তদের জন্য কাজ করে না তাই এটি সাধারণ সমাধান নয় solution
wim

14

সূচকের দ্বারা আইট্রেট করা একই কাজ করতে পারে:

#!/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

2020 সালের 16 ই মে এটি এখন একটি সাধারণ আমদানি

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)]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.