ترجمه - tuple in python




العثور على فهرس عنصر معين في قائمة تحتويه في Python (19)

للحصول على قائمة ["foo", "bar", "baz"] في قائمة "bar" ، كيف يمكنني الحصول على فهرسها (1) في Python؟


العثور على فهرس عنصر معين في قائمة تحتويه في Python

للحصول على قائمة ["foo", "bar", "baz"] في قائمة "bar" ، ما هي الطريقة الأنظف للحصول على فهرسها (1) في Python؟

حسنًا ، بالتأكيد ، هناك طريقة الفهرس ، التي تُرجع فهرس التواجد الأول:

>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1

هناك مشكلتان تتعلقان بهذه الطريقة:

  • إذا لم تكن القيمة في القائمة ، فستحصل على ValueError
  • إذا كان هناك أكثر من قيمة في القائمة ، فستحصل فقط على الفهرس الأول

لا قيم

إذا كانت القيمة مفقودة ، فستحتاج إلى ValueError .

يمكنك القيام بذلك باستخدام تعريف قابل لإعادة الاستخدام مثل هذا:

def index(a_list, value):
    try:
        return a_list.index(value)
    except ValueError:
        return None

واستخدمها على هذا النحو:

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

والجانب السلبي من هذا هو أنه سيكون لديك على الأرجح شيكًا إذا كانت القيمة التي is إرجاعها is أو is not :

result = index(a_list, value)
if result is not None:
    do_something(result)

أكثر من قيمة واحدة في القائمة

إذا كان بإمكانك الحصول على المزيد من التكرارات ، فلن تحصل على معلومات كاملة مع list.index :

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

قد تعداد في قائمة فهم الفهارس:

>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]

إذا لم يكن لديك أي تكرارات ، فيمكنك التحقق من ذلك من خلال التحقق المنطقي للنتيجة ، أو عدم القيام بأي إجراء إذا تخطت النتائج:

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

تحسين بيانات munging مع الباندا

إذا كان لديك حيوانات الباندا ، يمكنك بسهولة الحصول على هذه المعلومات مع كائن سلسلة:

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

فحص المقارنة سيعيد سلسلة من booleans:

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

مرر سلسلة booleans هذه إلى السلسلة عن طريق تدوين منخفض ، وستحصل فقط على الأعضاء المتطابقين:

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

إذا كنت ترغب فقط في الفهارس ، فسوف تُرجع سمة الفهرس سلسلة من الأعداد الصحيحة:

>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')

وإذا كنت تريدها في قائمة أو مجموعة ، فمررهم إلى المُنشئ:

>>> list(series[series == 'bar'].index)
[1, 3]

نعم ، يمكنك استخدام فهم قائمة مع تعداد أيضاً ، ولكن هذا ليس بالأناقة ، في رأيي - فأنت تقوم باختبارات للمساواة في بايثون ، بدلاً من ترك شفرة مبنية مكتوبة في C تعالجها:

>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]

هل هذه مشكلة س ص ؟

المشكلة XY تسأل عن الحل الخاص بك محاولة بدلاً من مشكلتك الفعلية.

لماذا تعتقد أنك بحاجة إلى إعطاء الفهرس عنصرًا في القائمة؟

إذا كنت تعرف القيمة بالفعل ، فلماذا تهتم بمكان وجودها في القائمة؟

إذا لم تكن القيمة موجودة ، فإن التقاط ValueError مطول بدلاً من ذلك - وأنا أفضل تجنب ذلك.

أنا عادة أكرر في القائمة على أي حال ، لذلك سأحتفظ عادة بمعلومات مفيدة ، مع الحصول على المؤشر مع التعداد.

إذا كنت تقوم بتدوير البيانات ، فمن المحتمل أنك تستخدم الباندا - التي لديها أدوات أكثر أناقة بكثير من طرق بايثون الصرفة التي عرضتها.

لا أذكر list.index بحاجة إلى list.index ، بنفسي. ومع ذلك ، فقد بحثت في مكتبة Python القياسية ، وأرى بعض الاستخدامات الممتازة لها.

هناك العديد من الاستخدامات لذلك في idlelib ، لواجهة المستخدم الرسومية والنص تحليل.

تستخدم الوحدة النمطية keyword للعثور على علامات تعليق في الوحدة النمطية إلى إعادة إنشاء قائمة الكلمات الأساسية فيه تلقائياً عبر metaprogramming.

في Lib / mailbox.py يبدو أنها تستخدمه كخريطة مرتبة:

key_list[key_list.index(old)] = new

و

del key_list[key_list.index(key)]

في Lib / http / cookiejar.py ، يبدو أنه سيتم استخدامه للحصول على الشهر التالي:

mon = MONTHS_LOWER.index(mon.lower())+1

في Lib / tarfile.py تشبه distutils للحصول على شريحة تصل إلى عنصر:

members = members[:members.index(tarinfo)]

في Lib / pickletools.py:

numtopop = before.index(markobject)

ما تشترك فيه هذه الاستخدامات هو أنه يبدو أنها تعمل على قوائم ذات أحجام مقيدة (مهمة بسبب O وقت البحث عن list.index ) ، وهي تستخدم في الغالب في list.index ( list.index المستخدم في حالة الخمول).

في حين أن هناك حالات الاستخدام لذلك ، فهي غير شائعة إلى حد ما. إذا وجدت نفسك تبحث عن هذه الإجابة ، اسأل نفسك عما إذا كان ما تفعله هو الاستخدام الأكثر مباشرة للأدوات المقدمة من اللغة لحالة الاستخدام الخاصة بك.


إذا كان الأداء يثير القلق:

وقد ورد في العديد من الإجابات أن الطريقة المضمنة في أسلوب list.index(item) هي خوارزمية O (n). لا بأس إذا كنت بحاجة إلى القيام بذلك مرة واحدة. ولكن إذا كنت تريد الوصول إلى مؤشرات العناصر عدة مرات ، فمن المنطقي أولاً إنشاء قاموس (O (n)) من أزواج فهرسة العنصر ، ثم الوصول إلى الفهرس في O (1) في كل مرة تحتاج ذلك.

إذا كنت متأكدًا من عدم تكرار العناصر الموجودة في القائمة مطلقًا ، فيمكنك بسهولة:

myList = ["foo", "bar", "baz"]

# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))

# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.

إذا كان لديك عناصر مكررة وتحتاج إلى إعادة جميع مؤشراتها:

from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]

# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
    myDict[e].append(i)

# Lookup
myDict["foo"] # Returns [0, 4]

الحصول على جميع التكرارات وموضع عنصر واحد أو أكثر (متطابقة) في قائمة

مع تعداد (alist) يمكنك تخزين العنصر الأول (n) الذي يعد فهرس القائمة عندما يكون العنصر x مساوياً لما تبحث عنه.

>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>

دعونا نجعل وظيفتنا findindex

تأخذ هذه الوظيفة العنصر والقائمة كوسائط وترجع موضع العنصر في القائمة ، كما رأينا من قبل.

def indexlist(item2find, list_or_string):
  "Returns all indexes of an item in a list or a string"
  return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))

انتاج |

[1, 3, 5, 7]

بسيط

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

انتاج:

0
4

إذا كنت تريد جميع الفهارس ، فيمكنك استخدام NumPy :

import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)

إنه حل واضح وقابل للقراءة.


ببساطة يمكنك الذهاب معه

a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]

بما أن قوائم بايثون تستند إلى الصفر ، يمكننا استخدام وظيفة zip المضمنة كما يلي:

>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]

حيث "haystack" هي القائمة في السؤال و "needle" هي العنصر المطلوب البحث عنه.

(ملاحظة: هنا نتحدث عن استخدام i للحصول على الفهارس ، ولكن إذا كنا بحاجة إلى التركيز على العناصر التي يمكننا التبديل إليها j.)


جميع الفهارس مع وظيفة zip :

get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]

print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')

جميع الوظائف المقترحة هنا تنتج سلوك اللغة الكامنة ولكن تحجب ما يحدث.

[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly

لماذا تكتب دالة ما مع معالجة الاستثناء إذا كانت اللغة توفر الطرق للقيام بما تريده بنفسك؟


دعونا نعطي الاسم lst إلى القائمة التي لديك. يمكن للمرء تحويل قائمة lst إلى مجموعة numpy array . ثم استخدم numpy.where للحصول على فهرس العنصر المختار في القائمة. فيما يلي الطريقة التي ستنفذ بها.

 import numpy as np lst = ["foo", "bar", "baz"] #lst: : 'list' data type lst_np = np.array(lst) #lst_np: 'numpy.ndarray' index = np.where( lst_np == 'bar')[0][0] #index: 'numpy.int64' data type print index 1 

ستظهر مشكلة إذا كان العنصر غير موجود في القائمة. هذه الوظيفة تتعامل مع المشكلة:

# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
    try:
        index_element = list_element.index(element)
        return index_element
    except ValueError:
        return None

شيء واحد مفيد حقًا في تعلم بايثون هو استخدام وظيفة المساعدة التفاعلية:

>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value
 |

والذي غالبًا ما يقودك إلى الطريقة التي تبحث عنها.


كما هو مبين فيTerryA ، تناقش إجابات كثيرة كيفية العثور على فهرس واحد .

more_itertools هي مكتبة تابعة لجهة خارجية بها أدوات لتحديد أماكن المؤشرات المتعددة في صيغة قابلة للتكرار.

معطى

import more_itertools as mit


iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]

الشفرة

البحث عن مؤشرات لملاحظات متعددة:

list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]

اختبار عناصر متعددة:

list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]

انظر أيضا المزيد من الخيارات مع more_itertools.locate . التثبيت عبر more_itertools .


للحصول على جميع الفهارس:

 indexes = [i for i,x in enumerate(xs) if x == 'foo']

هذا الحل ليس بنفس القوة التي يتمتع بها الآخرون ، ولكن إذا كنت مبتدئًا ولا تعرف سوى الحلقات ، فلا يزال من الممكن العثور على الفهرس الأول لعنصر ما مع تجنب ValueError:

def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1

هناك احتمالان إذا لم يكن لدى القائمة عناصر مكررة تحتاج إلى التحقق من الفهرس

 eg: li=[10,20,30] # here need to get index of 20 means
     li.index(20) # will work properly because 20 is not repeated

إذا كانت وسائله المتكررة ستعطيك فقط المؤشر الأول

إذا كنت بحاجة إلى الحصول على جميع الفهرس حيث يوجد العنصر يعني

eg: li=[10,20,30,20,40, 50, 10] # here need to get index of 20 means its have 2 index (1,3) 

للحصول على ما تحتاجه للقيام به

 li=[10,20,30,20,40, 50, 10]
 [i for i, e in enumerate(li) if e == 20]

عندها ستحصل على قائمة بالفهرس مثل o / p مثل [1]


يجب عليك تعيين شرط للتحقق مما إذا كان العنصر الذي تبحث عنه موجودًا في القائمة

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None

index() إرجاع فهرس القيمة الأول!

| فهرس(...)
| L.index (القيمة ، [start ، [stop]]) -> integer - return first index of value

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])

>>> ["foo", "bar", "baz"].index("bar")
1

المرجع: هياكل البيانات> المزيد عن القوائم

يتبع التحذيرات

لاحظ أنه على الرغم من أن هذا ربما كان أنظف طريقة للإجابة على السؤال كما هو مطلوب ، فإن index مكون ضعيف إلى حد ما في واجهة برمجة التطبيقات ، ولا أتذكر آخر مرة استخدمتها في الغضب. لقد أشير إلي في التعليقات أنه نظرًا لأن هذه الإجابة مشار إليها بكثرة ، يجب أن تكون أكثر اكتمالاً. بعض التحذيرات حول list.index اتبع. قد يكون من المفيد في البداية إلقاء نظرة على جمل docstring لها:

>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.

تعقيد زمني خطي في طول القائمة

تقوم مكالمة index بفحص كل عنصر في القائمة بالترتيب ، حتى تعثر على تطابق. إذا كانت قائمتك طويلة ، ولا تعرف تقريباً مكان ظهورها في القائمة ، فقد يصبح هذا البحث عنق زجاجة. في هذه الحالة ، يجب أن تفكر في بنية بيانات مختلفة. لاحظ أنه إذا كنت تعرف مكان العثور على المباراة تقريبًا ، فيمكنك إعطاء index تلميحًا. على سبيل المثال ، في هذا المقتطف ، يكون l.index(999_999, 999_990, 1_000_000) خمس مرات تقريبًا أسرع من l.index(999_999) ، لأن الأول فقط لديه البحث في 10 إدخالات ، بينما يبحث الأخير عن مليون مرة:

>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

يعيد فقط فهرس المطابقة الأولى إلى وسيطها

تبحث مكالمة index في القائمة بالترتيب حتى تعثر على تطابق ، وتتوقف هناك. إذا كنت تتوقع احتواء المزيد من المطابقات ، فعليك استخدام فهم قائمة أو تعبير مولد.

>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2

في معظم الأماكن التي استخدم فيها index مرة واحدة ، أستخدم الآن تعبيرًا أو تعبيرًا للمولدات لأنهما أكثر تعميمًا. إذا كنت تفكر في الوصول إلى index ، ألقِ نظرة على ميزات الثعبان الممتازة هذه.

يلقي إذا كان العنصر غير موجود في القائمة

ينتج عن استدعاء index في ValueError إذا كان العنصر غير موجود.

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 2 is not in list

إذا لم يكن العنصر موجودًا في القائمة ، فيجب عليك أيضًا

  1. تحقق لأول مرة مع item in my_list ( item in my_list نظيف وقابل للقراءة) ، أو
  2. التفاف استدعاء index في try/except كتلة الذي يمسك ValueError (ربما أسرع ، على الأقل عندما تكون قائمة للبحث طويلة ، ValueError عادة ما يكون موجودا.)

name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
    new_list.append(item[0])
print(new_list)
try:
    location= new_list.index(name)
except:
    location=-1
print (location)

هذه الحسابات إذا لم تكن السلسلة في القائمة أيضًا ، إذا لم تكن في القائمة ، فالمكان = -1





list