পাইথন তালিকার বোধগম্যতা ব্যবহার করে একটি শর্তের ভিত্তিতে উপাদানগুলির সূচকগুলি সন্ধান করা


119

নীচের পাইথন কোডটি মাতলাব পটভূমি থেকে আসার সময় খুব দীর্ঘ বাতাসযুক্ত বলে মনে হয়

>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]

মতলব কবে আমি লিখতে পারি:

>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
     3     6

পাইথনে এটি লেখার জন্য একটি ছোট হাত পদ্ধতি আছে, বা আমি কেবল দীর্ঘ সংস্করণটির সাথে লেগে আছি?


পাইথনের সিনট্যাক্সের জন্য যুক্তি সম্পর্কিত সমস্ত পরামর্শ এবং ব্যাখ্যা দেওয়ার জন্য আপনাকে ধন্যবাদ।

শূন্য ওয়েবসাইটটিতে নিম্নলিখিতগুলি সন্ধান করার পরে, আমি মনে করি যে আমি আমার পছন্দ মতো একটি সমাধান পেয়েছি:

http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays

উপরের আমার সমস্যার জন্য সেই ওয়েবসাইট থেকে তথ্য প্রয়োগ করা, নিম্নলিখিতগুলি দেবে:

>>> from numpy import array
>>> a = array([1, 2, 3, 1, 2, 3])
>>> b = a>2 
array([False, False, True, False, False, True], dtype=bool)
>>> r = array(range(len(b)))
>>> r(b)
[2, 5]

নিম্নলিখিতগুলির পরে কাজ করা উচিত (তবে এটি পরীক্ষা করার জন্য পাইথনের দোভাষী আমার হাতে নেই):

class my_array(numpy.array):
    def find(self, b):
        r = array(range(len(b)))
        return r(b)


>>> a = my_array([1, 2, 3, 1, 2, 3])
>>> a.find(a>2)
[2, 5]

6
কীভাবে [idx for idx in range(len(a)) if a[idx] > 2]? পাইথনে এটি করা কিছুটা বিশ্রী হওয়ার কারণ এটি অন্যান্য ভাষার মতো সূচিগুলি ব্যবহার করে না।
নালুউজারএক্সেপশন

উত্তর:


77
  • পাইথন, আপনি সব সময়ে এই জন্য ইনডেক্স ব্যবহার করা হবে না, কিন্তু values- সাথে মোকাবিলা [value for value in a if value > 2]। সাধারণত সূচকের সাথে ডিল করার অর্থ আপনি সর্বোত্তম উপায়ে কিছু করছেন না।

  • আপনি যদি না মতলব এর অনুরূপ একটি API, আপনি ব্যবহার করেন numpy বহুমাত্রিক অ্যারে এবং পাইথন সাংখ্যিক গণিত যা প্রচন্ডভাবে মতলব দ্বারা অনুপ্রাণিত হয় একটি প্যাকেজ। আপনি তালিকার পরিবর্তে একটি অদ্ভুত অ্যারে ব্যবহার করবেন।

    >>> import numpy
    >>> a = numpy.array([1, 2, 3, 1, 2, 3])
    >>> a
    array([1, 2, 3, 1, 2, 3])
    >>> numpy.where(a > 2)
    (array([2, 5]),)
    >>> a > 2
    array([False, False,  True, False, False,  True], dtype=bool)
    >>> a[numpy.where(a > 2)]
    array([3, 3])
    >>> a[a > 2]
    array([3, 3])

2
আপনার তালিকাগুলি রয়েছে, একটি রেঞ্জের জন্য এবং একটিতে কোণগুলির জন্য, আপনি কিছু স্তরের উপরে থাকা সীমার মানগুলি ফিল্টার করতে চান। কীভাবে আপনি "সেরা উপায়ে" ফ্যাশনে সেই ব্যাপ্তিগুলির সাথে সম্পর্কিত কোণগুলি কীভাবে ফিল্টার করবেন?
মেহেদী

3
filtered_ranges_and_angles = [(range, angle) for range, angle in zip(ranges, angles) if should_be_kept(range)]
মাইক গ্রাহাম

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

63

অন্য উপায়:

>>> [i for i in range(len(a)) if a[i] > 2]
[2, 5]

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

>>> def find_indices(lst, condition):
...   return [i for i, elem in enumerate(lst) if condition(elem)]
... 
>>> find_indices(a, lambda e: e > 2)
[2, 5]

নোট করুন যে আমি মাতলাবকে অনুকরণ করতে এখানে তালিকা ব্যবহার করছি। জেনারেটর এবং পুনরুক্তি ব্যবহার করা আরও পাইথনিক হবে।


2
ওপি [i for i,v in enumerate(a) if v > 2]পরিবর্তে এটি লিখতে পারে ।
নালুউজারএক্সেপশন

এটি খাটো নয়, এটি আরও দীর্ঘ। আসলটির indexসাথে iএবং valueসাথে প্রতিস্থাপন করুন এবং vঅক্ষরগুলি গণনা করুন।
agf

@ নুল ইউজার, অগফ: আপনি ঠিক বলেছেন, তবে মূল বিষয়টি দ্বিতীয় ভাগ :)
এলি বেন্ডারস্কি

1
enumerateওভার ব্যবহার করা range(len(...))আরও মজবুত এবং আরও কার্যকর।
মাইক গ্রাহাম

1
@ মাইক গ্রাহাম: আমি সম্মত - find_indicesব্যবহারের জন্য তেহ কার্যকারিতা পরিবর্তন করবেenumerate
এলি বেন্ডারস্কি


6

সম্ভবত আর একটি প্রশ্ন হ'ল "আপনি একবারে এই সূচকগুলি পাওয়ার পরে কি করবেন?" আপনি যদি তাদের অন্য একটি তালিকা তৈরি করতে ব্যবহার করতে যাচ্ছেন তবে পাইথনে, এগুলি একটি অপ্রয়োজনীয় মাঝারি পদক্ষেপ। আপনি যদি একটি প্রদত্ত শর্তের সাথে মেলে এমন সমস্ত মান চান তবে কেবল বিল্টিন ফিল্টারটি ব্যবহার করুন:

matchingVals = filter(lambda x : x>2, a)

অথবা আপনার নিজস্ব তালিকা সংকলন লিখুন:

matchingVals = [x for x in a if x > 2]

যদি আপনি এগুলি তালিকা থেকে মুছে ফেলতে চান তবে পাইথোনিক উপায়টি প্রয়োজনীয়ভাবে তালিকা থেকে অপসারণ করা নয়, তবে একটি তালিকা উপলব্ধি লিখুন যেন আপনি একটি নতুন তালিকা তৈরি করছেন, এবং listvar[:]বাম-হাতের সাহায্যে স্থানে ফিরে বরাদ্দ করুন -side:

a[:] = [x for x in a if x <= 2]

মতলব সরবরাহ করে findকারণ এর অ্যারে-কেন্দ্রিক মডেল তাদের অ্যারে সূচকগুলি ব্যবহার করে আইটেম নির্বাচন করে কাজ করে। আপনি পাইথনে এটি করতে পারেন , অবশ্যই, তবে আরও বেশি পাইথোনিক উপায়টি পুনরাবৃত্তকারী এবং জেনারেটর ব্যবহার করছে যা ইতিমধ্যে @ এলিবেেন্ডারস্কি দ্বারা উল্লিখিত রয়েছে।


পল, আমি এখনও কোনও স্ক্রিপ্ট / ফাংশন / শ্রেণিতে এটির প্রয়োজনীয়তা পাইনি। আমি যে ক্লাসটি লিখছি তার ইন্টারেক্টিভ পরীক্ষার জন্য এটি আরও বেশি।
লি

@ মাইক - সম্পাদনার জন্য ধন্যবাদ, তবে আমি আসলেই বলতে চাইছিলাম - a[:] = ...দেখুন অ্যালেক্স মার্তেলির এই প্রশ্নের উত্তর stackoverflow.com/questions/1352885/…
PaulMcG

@ পল, আমি ধরে নিয়েছি (এবং আশা করি!) আপনি আপনার বিবরণ থেকে আসলেই এটি বোঝাতে পারেন নি যে আপনি "একটি নতুন তালিকা তৈরি করতে চলেছেন"; আমি দেখতে পেয়েছি যে প্রোগ্রামগুলি যখন খুব অল্প পরিমাণে বিদ্যমান ডেটা পরিবর্তন করে তখন প্রোগ্রামগুলি বুঝতে এবং বজায় রাখার ঝোঁক থাকে। যে কোনও ইভেন্টে, আমি ওভারস্টেপ করার জন্য দুঃখিত - আপনি অবশ্যই নিজের পোস্টটি যা চান তা সম্পাদনা করতে সক্ষম হবেন।
মাইক গ্রাহাম

6

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

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

def indices(list, filtr=lambda x: bool(x)):
    return [i for i,x in enumerate(list) if filtr(x)]

print(indices([1,0,3,5,1], lambda x: x==1))

ফলন: [0, 4]

আমার কল্পনায় নিখুঁত উপায়টি হ'ল একটি শিশু শ্রেণীর তালিকা তৈরি করা এবং সূচকগুলি বর্গ পদ্ধতি হিসাবে যুক্ত করা। এইভাবে কেবল ফিল্টার পদ্ধতির প্রয়োজন হবে:

class MyList(list):
    def __init__(self, *args):
        list.__init__(self, *args)
    def indices(self, filtr=lambda x: bool(x)):
        return [i for i,x in enumerate(self) if filtr(x)]

my_list = MyList([1,0,3,5,1])
my_list.indices(lambda x: x==1)

আমি এখানে topic বিষয়টিতে আরও কিছু বিশদ বর্ণনা করেছি: http://tinyurl.com/jajrr87

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