বুলিয়ানগুলির তালিকার উপর ভিত্তি করে একটি তালিকা ফিল্টার করছে


127

আমার কাছে বুলিয়ানের একটি তালিকার মানগুলিকে ফিল্টার করার দরকারগুলির একটি তালিকা রয়েছে:

list_a = [1, 2, 4, 6]
filter = [True, False, True, False]

আমি নিম্নলিখিত লাইনের সাথে একটি নতুন ফিল্টারড তালিকা তৈরি করেছি:

filtered_list = [i for indx,i in enumerate(list_a) if filter[indx] == True]

যার ফলাফল:

print filtered_list
[1,4]

লাইনটি কাজ করে তবে (আমার কাছে) কিছুটা ওভারকিল দেখায় এবং আমি ভাবছিলাম যে এটির কোনও সহজ উপায় আছে কিনা।


উপদেশাবলী

নীচে উত্তরে দেওয়া দুটি ভাল পরামর্শ সংক্ষিপ্তসার:

1- filterআমার মতো তালিকার নাম রাখবেন না কারণ এটি একটি অন্তর্নির্মিত ফাংশন।

2- Trueআমার পছন্দ মতো জিনিসগুলির সাথে তুলনা করবেন না if filter[idx]==True..কারণ এটি অপ্রয়োজনীয়। শুধু ব্যবহার if filter[idx]যথেষ্ট।


3
শুধু এফওয়াইআই, এটি স্ট্রিম কমপ্যাকশন নামে পরিচিত একটি সাধারণ সমান্তরাল কম্পিউটিং আদিম । (একে 'আদিম' বলা হয় কারণ এটি সহজ নয়, কারণ এটি অন্যান্য বহু সমান্তরাল অ্যালগরিদমের জন্য বিল্ডিং ব্লক হিসাবে ব্যবহৃত হয়েছে)
ব্লুরাজা - ড্যানি প্লেগুয়েফট

2
কিছু শৈলী নোট: if filter[indx] == Trueনা না ব্যবহার ==আপনার সাথে পরিচয় যাচাই করতে চান তাহলে True, ব্যবহার is। যাইহোক এই ক্ষেত্রে পুরো তুলনা অকেজো, আপনি সহজভাবে ব্যবহার করতে পারেন if filter[indx]। শেষ অবধি: কোনও ভেরিয়েবল / মডিউল নাম হিসাবে অন্তর্নির্মিত নামটি কখনই ব্যবহার করবেন না (আমি নামটি উল্লেখ করছি filter)। এর মতো কিছু ব্যবহার করে included, যাতে ifসুন্দরভাবে পড়তে পারে ( if included[indx])।
বাকুরিউ

উত্তর:


184

আপনি খুঁজছেন itertools.compress:

>>> from itertools import compress
>>> list_a = [1, 2, 4, 6]
>>> fil = [True, False, True, False]
>>> list(compress(list_a, fil))
[1, 4]

সময় তুলনা (py3.x):

>>> list_a = [1, 2, 4, 6]
>>> fil = [True, False, True, False]
>>> %timeit list(compress(list_a, fil))
100000 loops, best of 3: 2.58 us per loop
>>> %timeit [i for (i, v) in zip(list_a, fil) if v]  #winner
100000 loops, best of 3: 1.98 us per loop

>>> list_a = [1, 2, 4, 6]*100
>>> fil = [True, False, True, False]*100
>>> %timeit list(compress(list_a, fil))              #winner
10000 loops, best of 3: 24.3 us per loop
>>> %timeit [i for (i, v) in zip(list_a, fil) if v]
10000 loops, best of 3: 82 us per loop

>>> list_a = [1, 2, 4, 6]*10000
>>> fil = [True, False, True, False]*10000
>>> %timeit list(compress(list_a, fil))              #winner
1000 loops, best of 3: 1.66 ms per loop
>>> %timeit [i for (i, v) in zip(list_a, fil) if v] 
100 loops, best of 3: 7.65 ms per loop

filterচলক নাম হিসাবে ব্যবহার করবেন না , এটি একটি অন্তর্নির্মিত ফাংশন।


@ মেহেদী আমি মতলব পথটিকে অত্যন্ত অপ্রচলিত মনে করি তবে আমি মনে করি এটি আপনার ব্যবহারের উপর নির্ভর করে।
আয়ান গোল্ডবাই

আমি কীভাবে নির্বাচন করতে পারি [2, 6]?
ফ্লোরেন্ট

আমি এটি পেয়েছি, list(compress(list_a, [not i for i in fill]))ফিরে আসা উচিত[2, 6]
ফ্লোরেন্ট

42

তাই ভালো:

filtered_list = [i for (i, v) in zip(list_a, filter) if v]

কোনও সূচকের প্রয়োজন ছাড়াই সমান্তরালভাবে একাধিক সিকোয়েন্সগুলির মাধ্যমে পুনরাবৃত্তি করার পাইথোনিক উপায়টি ব্যবহার করা zipহচ্ছে । এটি ধরে নিয়েছে যে উভয় ক্রমের একই দৈর্ঘ্য রয়েছে (সংক্ষিপ্ততম রান আউট হওয়ার পরে জিপ বন্ধ হয়ে যায়)। এত সাধারণ ক্ষেত্রে ব্যবহার করা কিছুটা ওভারকিল ...itertools

আপনার উদাহরণে আপনি যে কাজটি করা উচিত তা হ'ল জিনিসগুলির সাথে তুলনা করা সত্য, এটি সাধারণত প্রয়োজন হয় না। পরিবর্তেif filter[idx]==True: ... , আপনি কেবল লিখতে পারেন if filter[idx]: ...


40

নোংরা সহ:

In [128]: list_a = np.array([1, 2, 4, 6])
In [129]: filter = np.array([True, False, True, False])
In [130]: list_a[filter]

Out[130]: array([1, 4])

অথবা যদি তালিকা_এ একটি অদ্ভুত অ্যারে হতে পারে তবে ফিল্টার নয় তবে অ্যালেক্স জ্যাজমারির উত্তর দেখুন

নম্পি সাধারণত আপনাকে একটি বড় গতি বাড়িয়ে দেয়

In [133]: list_a = [1, 2, 4, 6]*10000
In [134]: fil = [True, False, True, False]*10000
In [135]: list_a_np = np.array(list_a)
In [136]: fil_np = np.array(fil)

In [139]: %timeit list(itertools.compress(list_a, fil))
1000 loops, best of 3: 625 us per loop

In [140]: %timeit list_a_np[fil_np]
10000 loops, best of 3: 173 us per loop

ভাল কথা, আমি যেখানে সম্ভব সেখানে ব্যবহার NumPyকরতে পছন্দ করি list। তবে যদি আপনার listযাইহোক ব্যবহারের প্রয়োজন হয় তবে আপনার উভয় তালিকা থেকেই NumPyসমাধান সমাধান ( সমাধান ব্যবহার করে) তৈরি np.arrayকরতে হবে, বুলিয়ান ইনডেক্সিং এবং অবশেষে অ্যারেটিকে tolist()পদ্ধতির সাথে তালিকায় ফিরে রূপান্তর করতে হবে । সুনির্দিষ্টভাবে বলতে গেলে, আপনাকে সেই সময়কালের তুলনায় এই অবজেক্টগুলি তৈরি করা উচিত। তারপরে, ব্যবহার itertools.compressকরা এখনও দ্রুততম সমাধান হবে।
নর্ক্সিস

17

নম্পটি ব্যবহার করে এটি করার জন্য, যদি আপনার aপরিবর্তে অ্যারে থাকে তবে list_a:

a = np.array([1, 2, 4, 6])
my_filter = np.array([True, False, True, False], dtype=bool)
a[my_filter]
> array([1, 4])

3
আপনি যদি মাই ফিল্টারটিকে একটি বুলিয়ান অ্যারে রূপান্তর করেন তবে আপনি প্রয়োজন ছাড়াই সরাসরি বুলিয়ান সূচক ব্যবহার করতে পারেন where
বাস সুইঙ্কসেলস


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