একটি অনুক্রমের সাথে মেলে এমন ক্রমের প্রথম উপাদানটি সন্ধান করুন


170

আমি কোনও তালিকার সাথে মেলে এমন তালিকার প্রথম উপাদানটি খুঁজে পেতে একটি মূর্তিযুক্ত উপায় চাই।

বর্তমান কোডটি বেশ কুৎসিত:

[x for x in seq if predicate(x)][0]

আমি এটিকে পরিবর্তন করার বিষয়ে ভেবেছিলাম:

from itertools import dropwhile
dropwhile(lambda x: not predicate(x), seq).next()

তবে আরও কিছু মার্জিত কিছু থাকতে হবে ... এবং এটি মিলবে Noneযদি কোনও মিল না পাওয়া যায় তবে ব্যতিক্রম বাড়ানোর পরিবর্তে এটি কোনও মান ফেরত দিলে ভাল লাগবে ।

আমি জানি আমি কেবল একটি ফাংশন সংজ্ঞায়িত করতে পারলাম:

def get_first(predicate, seq):
    for i in seq:
        if predicate(i): return i
    return None

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


2
" পাইথন সিক্যুয়েন্স ফাইন্ড ফাংশন " এর চেয়ে পরে জিজ্ঞাসা করা ছাড়াও , এই প্রশ্নের আরও একটি শিরোনাম রয়েছে
উলফ

উত্তর:


249

এর সাথে seqমেলে এমন ক্রমের প্রথম উপাদানটি সন্ধান করতে predicate:

next(x for x in seq if predicate(x))

বা ( itertools.ifilterপাইথন 2 এ) :

next(filter(predicate, seq))

এটি StopIterationযদি না থাকে তবে উত্থাপিত হয়।


Noneজাতীয় কোনও উপাদান না থাকলে ফিরে যেতে:

next((x for x in seq if predicate(x)), None)

বা:

next(filter(predicate, seq), None)

27
অথবা আপনি nextএটি ব্যতীত উত্থাপনের পরিবর্তে ব্যবহৃত হয় দ্বিতীয় "ডিফল্ট" যুক্তি সরবরাহ করতে পারেন ।
কার্ল নচেটেল

2
@ ফিফর্টান: next()পাইথন ২.২ থেকে পাওয়া যায় আপনি দ্রুত নতুন বৈশিষ্ট্যগুলির সাথে নিজেকে পরিচিত করতে আপনি নতুন পৃষ্ঠাটি পড়তে পারেন ।
jfs

1
আমি একটি অজগর নবাগত এবং ডকগুলি পড়েছি এবং আইফিল্টারটি "ফলন" পদ্ধতিটি ব্যবহার করে। আমি ধরে নিলাম এর অর্থ হ'ল যে প্রেডিকেটটি আমাদের যেতে যেতে অলসভাবে মূল্যায়ন করা হয়। অর্থাত্, আমরা পুরো তালিকার মধ্য দিয়ে ভবিষ্যদ্বাণীটি চালাতে পারি না কারণ আমার কাছে একটি প্রাকটিক্যাল ফাংশন রয়েছে যা কিছুটা ব্যয়বহুল এবং আমি কেবল সেই
জায়গাটি

2
@ জিেকাজয়েড: seq.find(&method(:predicate))বা উদাহরণের পদ্ধতির জন্য আরও সংক্ষিপ্ত উদাহরণ যেমন:[1,1,4].find(&:even?)
জেফস

16
ifilterfilterপাইথন 3 এ নতুন নামকরণ করা হয়েছিল
tsauerwein

92

আপনি একটি জেনারেটর এক্সপ্রেশন ব্যবহার করতে পারেন একটি ডিফল্ট মান এবং তারপরে next:

next((x for x in seq if predicate(x)), None)

যদিও এই ওয়ান-লাইনারের জন্য আপনাকে পাইথন> = 2.6 ব্যবহার করা উচিত।

বরং এটি জনপ্রিয় নিবন্ধটি এই ইস্যুটি নিয়ে আরও আলোচনা করে: ক্লিস্টেস্ট পাইথন-সন্ধানী-তালিকার ফাংশন?


8

আমি মনে করি না যে আপনি আপনার প্রশ্নের প্রস্তাবিত সমাধানগুলির সাথে কোনও সমস্যা আছে।

আমার নিজস্ব কোডে, আমি এটিকে এ জাতীয় বাস্তবায়িত করব যদিও:

(x for x in seq if predicate(x)).next()

সহ সিনট্যাক্স ()একটি জেনারেটর তৈরি করে, যা একবারে সমস্ত তালিকা তৈরির চেয়ে কার্যকর []


এবং কেবল []এটিই নয় - আপনার সাথে সমস্যার মধ্যে পড়তে পারে যদি পুনরুক্তিকারী কখনও না শেষ হয় বা এর উপাদানগুলি তৈরি করা শক্ত হয় না তবে পরে তা হয়ে যায় ...
glglgl

6
'generator' object has no attribute 'next'পাইথন 3 এ
jfs

@glglgl - প্রথম দফার জন্য (কখনই শেষ হয় না) আমি সন্দেহ করি কারণ যুক্তিটি সীমাবদ্ধ ক্রম [আরও স্পষ্টভাবে ওপি'র প্রশ্ন অনুসারে একটি তালিকা]। দ্বিতীয় হিসাবে: আবার, যেহেতু সরবরাহিত আর্গুমেন্টটি একটি ক্রম, তাই এই ফাংশনটি বলা হওয়ার আগে অবজেক্টগুলি ইতিমধ্যে তৈরি করা এবং সংরক্ষণ করা উচিত ছিল .... অথবা আমি কিছু হারিয়ে যাচ্ছি?
ম্যাক

@ জেফাসেবাস্টিয়ান - ধন্যবাদ, আমি সে সম্পর্কে অবগত ছিলাম না! :) কৌতূহলের বাইরে এই পছন্দটির পিছনে ডিজাইনের নীতিটি কী?
ম্যাক

@ ম্যাক - অন্যান্য বিশেষ পদ্ধতির ডাবল আন্ডারস্কোরের সাথে সামঞ্জস্যের জন্য। পাইথন.অর্গ
চেভি

1

জেএফ সেবাস্তিয়ান এর উত্তর সর্বাধিক মার্জিত, তবে অজগর ২.6 দরকার ফোর্টারান নির্দেশিত হিসাবে।

পাইথন সংস্করণ <2.6 এর জন্য, আমি এখানে সেরা আসতে পারি:

from itertools import repeat,ifilter,chain
chain(ifilter(predicate,seq),repeat(None)).next()

বিকল্প হিসাবে যদি আপনার পরে কোনও তালিকার প্রয়োজন হয় (তালিকাটি স্টপআইটারেশন পরিচালনা করে), বা আপনার প্রথমটির চেয়ে আরও বেশি প্রয়োজন তবে এখনও সমস্ত না, আপনি এটি আইসিস দিয়ে করতে পারেন:

from itertools import islice,ifilter
list(islice(ifilter(predicate,seq),1))

আপডেট: যদিও আমি ব্যক্তিগতভাবে প্রথম () নামে একটি পূর্বনির্ধারিত ফাংশনটি ব্যবহার করছি যা একটি স্টপ ইন্টেরেশন ধরা পড়ে এবং কোনওটি প্রদান করে না, তবে উপরের উদাহরণের চেয়ে সম্ভাব্য উন্নতি এখানে রয়েছে: ফিল্টার / আইফিল্টার ব্যবহার এড়িয়ে চলুন:

from itertools import islice,chain
chain((x for x in seq if predicate(x)),repeat(None)).next()

11
বাবা! যদি এটি নেমে আসে তবে আমি কেবল "ভিতরে" একটি "যদি" দিয়ে লুপের জন্য সহজ করতাম - পড়তে অনেক সহজ
নিক পার্কিনস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.