একটি পুনরুদ্ধারকারী একটি পুনরুক্তি কমপক্ষে একটি উপাদান উত্পাদন করে কিনা তা পরীক্ষা করতে?


105

বর্তমানে আমি এটি করছি:

try:
    something = iterator.next()
    # ...
except StopIteration:
    # ...

তবে আমি একটি অভিব্যক্তি চাই যা আমি একটি সাধারণ ifবিবৃতিতে রাখতে পারি। এমন কোনও বিল্ট-ইন রয়েছে যা এই কোডটিকে কম আনাড়ি দেখাবে?

any()Falseযদি কোনও পুনরাবৃত্তযোগ্য শূন্য থাকে তবে ফেরত দেয় , তবে এটি যদি না হয় তবে সমস্ত আইটেমের উপর এটি সম্ভাব্যভাবে পুনরাবৃত্তি করবে। আমার কেবল প্রথম আইটেমটি পরীক্ষা করতে হবে।


কেউ জিজ্ঞাসা করছে আমি কী করতে চাইছি। আমি একটি ফাংশন লিখেছি যা একটি এসকিউএল কোয়েরি কার্যকর করে এবং এর ফলাফল দেয়। কখনও কখনও আমি যখন এই ফাংশনটি কল করি তখনই আমি জানতে চাইছি যে কোয়েরিটি কোনও কিছু ফিরে পেয়েছে এবং তার ভিত্তিতে কোনও সিদ্ধান্ত নিয়েছে।


4
এছাড়াও কোডটির সাথে একটি সমস্যা হ'ল আপনি এটিকে কোনও ফাংশনে প্যাকেজ করতে পারবেন না, কারণ এটি প্রথম উপাদানটি খাবে। ভাল প্রশ্ন.
অ্যান্ড্রুক

4
আমার ক্ষেত্রে আমার একেবারে এলিমেন্টের দরকার নেই, আমি কেবল জানতে চাই কমপক্ষে একটি উপাদান রয়েছে।
বাসটিয়েন লোনার্ডার্ড

4
হাহ! আমার একই ব্যবহারের ক্ষেত্রে একই সমাধানটি সন্ধান করার চেষ্টা করা হচ্ছে!
ড্যানিয়েল

সংশ্লিষ্ট: stackoverflow.com/q/661603/281545
Mr_and_Mrs_D

উত্তর:


137

anyএটি সত্য হলে প্রথম উপাদানটির বাইরে যাবে না। যদি আইটারেটর কিছু ফল দেয় তবে আপনি লিখতে পারেন any(True for _ in iterator)


এটি আমার জন্য কাজ করছে বলে মনে হচ্ছে, একটি রি-ফাইন্ডার। আপনি প্রথম টেস্টে যে কোনও স্টপ সহজেই থামাতে পারবেন তা সহজেই পরীক্ষা করতে পারেন: চালান any((x > 100 for x in xrange(10000000)))এবং তারপরে রান করুন any((x > 10000000 for x in xrange(100000000)))- দ্বিতীয়টিকে আরও বেশি সময় নিতে হবে।
chbrown

4
এটি "কমপক্ষে এক্স" এর ক্ষেত্রে কাজ করেsum(1 for _ in itertools.islice(iterator, max_len)) >= max_len
ডেভ বাটলার

11
একইভাবে আপনার যদি পুনরুক্তি খালি আছে কিনা তা খতিয়ে দেখার প্রয়োজন হলে পুনরুক্তিটি খালি all(False for _ in iterator)কিনা তা ব্যবহার করতে পারে । (সমস্ত আয় যদি সত্য হয় পুনরুক্তিকারীর খালি থাকে, অন্যথায় এটি স্টপ যখন এটি প্রথম মিথ্যা উপাদান সূচিত)
KGardevoir

24
এই সমাধানটির সাথে বড় সমস্যাটি হ'ল আপনি খালি না হয়ে আসলে পুনরুক্তিযোগ্য মানটি ব্যবহার করতে পারবেন না, তাই না?
কেন উইলিয়ামস

42

পাইথন ২.6+ তে, যদি নামটি sentinelএমন কোনও মানের সাথে আবদ্ধ হয় যা পুনরাবৃত্তিকারী সম্ভবত ফল দিতে পারে না,

if next(iterator, sentinel) is sentinel:
    print('iterator was empty')

যদি আপনার পুনরাবৃত্তিটি সম্ভবত ফল দিতে পারে তার কোনও ধারণা না থাকলে আপনার নিজের সেন্ডিনেলটি তৈরি করুন (উদাহরণস্বরূপ আপনার মডিউলের শীর্ষে) দিয়ে

sentinel = object()

অন্যথায়, আপনি সেন্ডিনেল ভূমিকার ক্ষেত্রে, যে কোনও মান যা আপনি "জানেন" (অ্যাপ্লিকেশন বিবেচনার ভিত্তিতে) ব্যবহার করতে পারেন যা সম্ভবত পুনরুক্তি দিতে পারে না।


4
সুন্দর! আমার ব্যবহারের ক্ষেত্রে, if not next(iterator, None):যথেষ্ট ছিল কারণ আমি নিশ্চিত যে আইটেমগুলির কোনও অংশই হবে না। আমাকে সঠিক দিকে নির্দেশ করার জন্য ধন্যবাদ!
wasabigeek

4
@ ওয়াসাবি মনে রাখবেন যে notখালি তালিকা, মিথ্যা এবং শূন্যের মতো কোনও মিথ্যা বস্তুর জন্য সত্য ফিরে আসবে। is not Noneনিরাপদ এবং আমার মতে আরও পরিষ্কার।
Caagr98

21

এটি সত্যিই পরিষ্কার নয়, তবে এটি কোনও কার্যবিহীনভাবে এটি প্যাকেজ করার উপায় দেখায়:

def has_elements(iter):
  from itertools import tee
  iter, any_check = tee(iter)
  try:
    any_check.next()
    return True, iter
  except StopIteration:
    return False, iter

has_el, iter = has_elements(iter)
if has_el:
  # not empty

এটি সত্যই পাইথোনিক নয় এবং নির্দিষ্ট ক্ষেত্রে সম্ভবত পরবর্তী ডিফল্টর মতো আরও ভাল (তবে কম সাধারণ) সমাধান রয়েছে ।

first = next(iter, None)
if first:
  # Do something

এটি সাধারণ নয় কারণ অনেকগুলি পুনরাবৃত্তিতে কোনওটিই বৈধ উপাদান হতে পারে না।


এটি সম্ভবত এটি করার সেরা উপায়। তবে এটি ওপি কী করার চেষ্টা করছে তা জানতে সহায়তা করবে? এর থেকে সম্ভবত আরও মার্জিত সমাধান রয়েছে (এটি হ'ল পাইথন, সর্বোপরি)।
রসপিডিয়া

ধন্যবাদ, আমি মনে করি আমি ব্যবহার করতে যাচ্ছি next()
বাসটিয়েন লোনার্ডার্ড

4
@Bastien, জরিমানা, কিন্তু একটি উপযুক্ত যাতে না প্রহরী (আমার উত্তর দেখুন)।
অ্যালেক্স মার্টেলি

4
এই সমাধানে একটি বিশাল মেমরি ফুটো আছে। teeItertools প্রতিটি উপাদান মূল পুনরুক্তিকারীর থেকে ক্ষেত্রে রাখতে হবে any_checkআগাম আগের চাহিদা। আসল পুনরাবৃত্তিকে তালিকায় রূপান্তর করার চেয়ে এটি আরও খারাপ।
রাফা ডগির্ড

4
@ রাফাডউগার্ড এটি কেবলমাত্র মূল পুনরুত্থককে একটি তালিকায় রূপান্তর করার চেয়ে খারাপ। আসলেই নয় - অসীম অনুক্রম সম্পর্কে চিন্তা করুন।
পাইওটর ডব্রোগোস্ট

6

তুমি ব্যবহার করতে পার:

if zip([None], iterator):
    # ...
else:
    # ...

তবে কোড পাঠকের জন্য এটি কিছুটা বিপরীত নয়


4
.. (আপনি [কোনও কিছুই নয়] এর পরিবর্তে যেকোনও 1-আইটেম পুনরাবৃত্ত করতে পারেন)
মাইখাল

5

যে কাজ করতে সবচেয়ে ভালো উপায় একটি সাথে আছেন peekableথেকে more_itertools

from more_itertools import peekable
iterator = peekable(iterator)
if iterator:
    # Iterator is non-empty.
else:
    # Iterator is empty.

আপনি যদি পুরানো পুনরুক্তিকারীর কাছ থেকে রেফ রেখে থাকেন তবে কেবল সতর্ক থাকুন, সেই পুনরুক্তিটি উন্নত হবে। তার পর থেকে আপনাকে নতুন দর্শনীয় পুনরুক্তি ব্যবহার করতে হবে। সত্যই, যদিও, তত্ক্ষণাতনকালে সেই পুরানো পুনরুক্তি সংশোধনকারী কোডের একমাত্র বিট হওয়ার প্রত্যাশা রয়েছে, সুতরাং আপনি যে কোনওভাবেই পুরানো পুনরুক্তিকারীকে রেফ রাখবেন না।


3

কি সম্পর্কে:

In [1]: i=iter([])

In [2]: bool(next(i,False))
Out[2]: False

In [3]: i=iter([1])

In [4]: bool(next(i,False))
Out[4]: True

4
আকর্ষণীয় এক! তবে যদি পরবর্তী () মিথ্যা ফিরিয়ে দেয় কারণ এটি যা সত্যতই উত্পন্ন হয়েছিল?
বাসটিয়েন লোনার্ডার্ড

@ বাস্তিয়ানলোনার্ড একটি ক্লাস তৈরি করুন class NotSet: pass, তারপরে পরীক্ষা করুনif next(i, NotSet) is NotSet: print("Iterator is empty")
এলিজাস দাপাউসকাস

-1

__length_hint__ দৈর্ঘ্য অনুমান করে list(it)- এটি ব্যক্তিগত পদ্ধতি, যদিও:

x = iter( (1, 2, 3) )
help(x.__length_hint__)
      1 Help on built-in function __length_hint__:
      2 
      3 __length_hint__(...)
      4     Private method returning an estimate of len(list(it)).

4
প্রতিটি পুনরুক্তিকারী জন্য গ্যারান্টিযুক্ত না। >>> এটিকে ডিফল্ট করুন (): ... ফলন 1 ... ফলন 2 ... ফলন 3 ... >>> আমি = এটি () >>> i .__ দৈর্ঘ্য_চিন্তা__ ট্রেসব্যাক (সর্বশেষতম কল শেষ): ফাইল " <মডেল> "লাইন 1, < মডুল > অ্যাট্রিবিউটার এয়ারে : 'জেনারেটর' অবজেক্টটির ' দৈর্ঘ্য_হিন্ট '
অ্যাট্রিউক

4
এটি কেবল একটি ইঙ্গিত হিসাবে শূন্যের চেয়ে বেশি এন্ট্রিযুক্ত একটি পুনরাবৃত্তির জন্য এটি 0 ফেরত পাওয়াও আইনী।
গ্লেন মেইনার্ড

-1

এটি একটি ওভারকিল আয়রেটর মোড়ক যা সাধারণত পরের কোনও আইটেম আছে কিনা তা পরীক্ষা করতে দেয় (বুলিয়ান রূপান্তরের মাধ্যমে)। অবশ্যই বেশ অদক্ষ।

class LookaheadIterator ():

    def __init__(self, iterator):
        self.__iterator = iterator
        try:
            self.__next      = next (iterator)
            self.__have_next = True
        except StopIteration:
            self.__have_next = False

    def __iter__(self):
        return self

    def next (self):
        if self.__have_next:
            result = self.__next
            try:
                self.__next      = next (self.__iterator)
                self.__have_next = True
            except StopIteration:
                self.__have_next = False

            return result

        else:
            raise StopIteration

    def __nonzero__(self):
        return self.__have_next

x = LookaheadIterator (iter ([]))
print bool (x)
print list (x)

x = LookaheadIterator (iter ([1, 2, 3]))
print bool (x)
print list (x)

আউটপুট:

False
[]
True
[1, 2, 3]

-2

কিছুটা দেরি হলেও আপনি পুনরুক্তিটিকে একটি তালিকায় পরিণত করতে পারেন এবং সেই তালিকাটি নিয়ে কাজ করতে পারেন:

# Create a list of objects but runs out the iterator.
l = [_ for _ in iterator]

# If the list is not empty then the iterator had elements; else it was empty.
if l :
    pass # Use the elements of the list (i.e. from the iterator)
else :
    pass # Iterator was empty, thus list is empty.

4
এটি অকার্যকর কারণ এটি পুরো তালিকাটি গণনা করে। অসীম জেনারেটরের জন্য কাজ করবে না।
বেকো

@ বেকো: একমত তবে এটি মূল প্রশ্নের ক্ষেত্রে মনে হয় না।
জেনস

4
আরেকটি সমস্যা হ'ল পুনরুক্তিকারী একটি সীমাহীন পরিমাণে অবজেক্ট তৈরি করতে পারে যা মেমরির ওভারফ্লোতে পরিণত হতে পারে এবং প্রোগ্রামটি পরবর্তী বিবৃতিতে কখনই পৌঁছাতে পারে না
উইলেম ভ্যান ওনসেম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.