উত্তর:
আপনি একটি জেনারেটর এক্সপ্রেশন ব্যবহার করতে পারেন :
>>> dicts = [
... { "name": "Tom", "age": 10 },
... { "name": "Mark", "age": 5 },
... { "name": "Pam", "age": 7 },
... { "name": "Dick", "age": 12 }
... ]
>>> next(item for item in dicts if item["name"] == "Pam")
{'age': 7, 'name': 'Pam'}
আপনার যদি আইটেমটি না থাকার হ্যান্ডেল করার প্রয়োজন হয়, তবে আপনি ব্যবহারকারী ম্যাট তার মন্তব্যে যা বলেছিলেন তা করতে পারেন এবং কিছুটা আলাদা এপিআই ব্যবহার করে একটি ডিফল্ট সরবরাহ করতে পারেন :
next((item for item in dicts if item["name"] == "Pam"), None)
এবং আইটেমটির সূচি খুঁজে পেতে আইটেমটি নিজের চেয়ে, আপনি তালিকাটি গণনা করতে পারেন :
next((i for i, item in enumerate(dicts) if item["name"] == "Pam"), None)
[item for item in dicts if item["name"] == "Pam"][0]
?
enumerate()
একটি চলমান সূচক জেনারেট করতে: next(i for i, item in enumerate(dicts) if item["name"] == "Pam")
।
এটি আমার কাছে সর্বাধিক পাইথোনিক উপায়ে দেখায়:
people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]
filter(lambda person: person['name'] == 'Pam', people)
ফলাফল (পাইথন 2 এ তালিকা হিসাবে ফিরে এসেছে):
[{'age': 7, 'name': 'Pam'}]
দ্রষ্টব্য: পাইথন 3 এ, একটি ফিল্টার অবজেক্ট ফিরে আসে। সুতরাং পাইথন 3 সমাধানটি হ'ল:
list(filter(lambda person: person['name'] == 'Pam', people))
len()
কল করতে হবে list()
। বা: stackoverflow.com/questions/19182188/...
r
একটিlist
next(filter(lambda x: x['name'] == 'Pam', dicts))
@ ফ্রিডরিক হামিদির উত্তর দুর্দান্ত। পাইথন 3.x এ সিন্টেক্সটি .next()
কিছুটা পরিবর্তিত হয়েছে। এইভাবে একটি সামান্য পরিবর্তন:
>>> dicts = [
{ "name": "Tom", "age": 10 },
{ "name": "Mark", "age": 5 },
{ "name": "Pam", "age": 7 },
{ "name": "Dick", "age": 12 }
]
>>> next(item for item in dicts if item["name"] == "Pam")
{'age': 7, 'name': 'Pam'}
@ ম্যাট দ্বারা মন্তব্যে উল্লিখিত হিসাবে, আপনি এর মধ্যে একটি ডিফল্ট মান যুক্ত করতে পারেন:
>>> next((item for item in dicts if item["name"] == "Pam"), False)
{'name': 'Pam', 'age': 7}
>>> next((item for item in dicts if item["name"] == "Sam"), False)
False
>>>
আপনি একটি তালিকা বোধগম্যতা ব্যবহার করতে পারেন :
def search(name, people):
return [element for element in people if element['name'] == name]
people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]
def search(name):
for p in people:
if p['name'] == name:
return p
search("Pam")
def search(list, key, value): for item in list: if item[key] == value: return item
অভিধানের তালিকাগুলির মধ্য দিয়ে যাওয়ার জন্য এবং কী x এর একটি নির্দিষ্ট মান রয়েছে এমন অভিধানগুলি ফিরিয়ে দেওয়ার জন্য আমি বিভিন্ন পদ্ধতি পরীক্ষা করেছি।
ফলাফল:
পাইথন 3.6 .4, ডাব্লু 7 এক্স 64 দিয়ে সমস্ত পরীক্ষা করা হয়েছে ।
from random import randint
from timeit import timeit
list_dicts = []
for _ in range(1000): # number of dicts in the list
dict_tmp = {}
for i in range(10): # number of keys for each dict
dict_tmp[f"key{i}"] = randint(0,50)
list_dicts.append( dict_tmp )
def a():
# normal iteration over all elements
for dict_ in list_dicts:
if dict_["key3"] == 20:
pass
def b():
# use 'generator'
for dict_ in (x for x in list_dicts if x["key3"] == 20):
pass
def c():
# use 'list'
for dict_ in [x for x in list_dicts if x["key3"] == 20]:
pass
def d():
# use 'filter'
for dict_ in filter(lambda x: x['key3'] == 20, list_dicts):
pass
ফলাফল:
1.7303 # normal list iteration
1.3849 # generator expression
1.3158 # list comprehension
7.7848 # filter
@ ফ্রাডেরিকহমিদিতে কেবল একটি ছোট্ট বিট যোগ করতে।
আপনি যদি নিশ্চিত না হন যে কোনও কী কী ডিক্টের তালিকায় রয়েছে তবে এর মতো কিছু আপনাকে সহায়তা করবে:
next((item for item in dicts if item.get("name") and item["name"] == "Pam"), None)
item.get("name") == "Pam"
আপনি কি কখনও পান্ডাস প্যাকেজ ব্যবহার করে দেখেছেন? এটি এই জাতীয় অনুসন্ধান কাজের জন্য নিখুঁত এবং অনুকূলিতও।
import pandas as pd
listOfDicts = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
# Create a data frame, keys are used as column headers.
# Dict items with the same key are entered into the same respective column.
df = pd.DataFrame(listOfDicts)
# The pandas dataframe allows you to pick out specific values like so:
df2 = df[ (df['name'] == 'Pam') & (df['age'] == 7) ]
# Alternate syntax, same thing
df2 = df[ (df.name == 'Pam') & (df.age == 7) ]
বড় আকারের অর্থাত্ 100k + এন্ট্রিগুলিতে পান্ডার দ্রুততম রানটাইম চিত্রিত করতে নীচে আমি কিছুটা বেঞ্চমার্ক যুক্ত করেছি:
setup_large = 'dicts = [];\
[dicts.extend(({ "name": "Tom", "age": 10 },{ "name": "Mark", "age": 5 },\
{ "name": "Pam", "age": 7 },{ "name": "Dick", "age": 12 })) for _ in range(25000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(dicts);'
setup_small = 'dicts = [];\
dicts.extend(({ "name": "Tom", "age": 10 },{ "name": "Mark", "age": 5 },\
{ "name": "Pam", "age": 7 },{ "name": "Dick", "age": 12 }));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(dicts);'
method1 = '[item for item in dicts if item["name"] == "Pam"]'
method2 = 'df[df["name"] == "Pam"]'
import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))
t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method Pandas: ' + str(t.timeit(100)))
#Small Method LC: 0.000191926956177
#Small Method Pandas: 0.044392824173
#Large Method LC: 1.98827004433
#Large Method Pandas: 0.324505090714
names = [{'name':'Tom', 'age': 10}, {'name': 'Mark', 'age': 5}, {'name': 'Pam', 'age': 7}]
resultlist = [d for d in names if d.get('name', '') == 'Pam']
first_result = resultlist[0]
এটি একটি উপায় ...
পাইথনের ফিল্টার এবং পরবর্তী পদ্ধতি ব্যবহার করে আপনি এটি অর্জন করতে পারেন।
filter
পদ্ধতি প্রদত্ত ক্রমটি ফিল্টার করে এবং একটি পুনরাবৃত্তিকে দেয়।
next
পদ্ধতিটি একটি পুনরাবৃত্তি গ্রহণ করে এবং তালিকার পরবর্তী উপাদানটি প্রদান করে।
সুতরাং আপনি উপাদানটি খুঁজে পেতে পারেন,
my_dict = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
next(filter(lambda obj: obj.get('name') == 'Pam', my_dict), None)
এবং আউটপুট হয়,
{'name': 'Pam', 'age': 7}
দ্রষ্টব্য: None
আমরা যে নামটি অনুসন্ধান করছি তা যদি খুঁজে না পাওয়া যায় তবে উপরের কোডটি যদি ফিরে আসবে ।
আমার প্রথম চিন্তাটি হ'ল আপনি এই অভিধানগুলির একটি অভিধান তৈরি করার কথা বিবেচনা করতে পারেন ... উদাহরণস্বরূপ, আপনি যদি এটি অল্প সংখ্যক বারের চেয়ে বেশি অনুসন্ধান করতে যাচ্ছেন।
তবে এটি একটি অকাল অপ্টিমাইজেশন হতে পারে। এর সাথে কী ভুল হবে:
def get_records(key, store=dict()):
'''Return a list of all records containing name==key from our store
'''
assert key is not None
return [d for d in store if d['name']==key]
dicts=[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
from collections import defaultdict
dicts_by_name=defaultdict(list)
for d in dicts:
dicts_by_name[d['name']]=d
print dicts_by_name['Tom']
#output
#>>>
#{'age': 10, 'name': 'Tom'}
আপনি এটি চেষ্টা করতে পারেন:
''' lst: list of dictionaries '''
lst = [{"name": "Tom", "age": 10}, {"name": "Mark", "age": 5}, {"name": "Pam", "age": 7}]
search = raw_input("What name: ") #Input name that needs to be searched (say 'Pam')
print [ lst[i] for i in range(len(lst)) if(lst[i]["name"]==search) ][0] #Output
>>> {'age': 7, 'name': 'Pam'}
এখানে পুনরাবৃত্ত থ্রোহগ তালিকাটি ব্যবহার করে ফিল্টার + ল্যাম্বদা বা রিফ্যাক্টরিং (যদি প্রয়োজন হয় বা আপনার ক্ষেত্রে বৈধ হয়) আপনার কোডটি ডিক্টের তালিকার চেয়ে ডিক্টের ডিকের সাথে তুলনা করুন
import time
# Build list of dicts
list_of_dicts = list()
for i in range(100000):
list_of_dicts.append({'id': i, 'name': 'Tom'})
# Build dict of dicts
dict_of_dicts = dict()
for i in range(100000):
dict_of_dicts[i] = {'name': 'Tom'}
# Find the one with ID of 99
# 1. iterate through the list
lod_ts = time.time()
for elem in list_of_dicts:
if elem['id'] == 99999:
break
lod_tf = time.time()
lod_td = lod_tf - lod_ts
# 2. Use filter
f_ts = time.time()
x = filter(lambda k: k['id'] == 99999, list_of_dicts)
f_tf = time.time()
f_td = f_tf- f_ts
# 3. find it in dict of dicts
dod_ts = time.time()
x = dict_of_dicts[99999]
dod_tf = time.time()
dod_td = dod_tf - dod_ts
print 'List of Dictionries took: %s' % lod_td
print 'Using filter took: %s' % f_td
print 'Dict of Dicts took: %s' % dod_td
এবং আউটপুটটি হ'ল:
List of Dictionries took: 0.0099310874939
Using filter took: 0.0121960639954
Dict of Dicts took: 4.05311584473e-06
উপসংহার: স্পষ্টতই ডিক্টের অভিধান থাকাই সেই ক্ষেত্রে সন্ধান করার পক্ষে সবচেয়ে কার্যকর উপায়, যেখানে আপনি জানেন যে আপনি কেবল আইডির মাধ্যমে অনুসন্ধান করবেন searching আকর্ষণীয়ভাবে ফিল্টার ব্যবহার করা সবচেয়ে ধীর সমাধান।
আপনাকে তালিকার সমস্ত উপাদান দিয়ে যেতে হবে। শর্টকাট নেই!
অন্য কোথাও না থাকলে তালিকার আইটেমগুলিকে নির্দেশ করে নামের একটি অভিধান রাখুন, তবে তারপরে আপনাকে আপনার তালিকা থেকে কোনও উপাদান পপ করার পরিণতিগুলি যত্ন নিতে হবে।
আমি যখন একই প্রশ্নের উত্তর খুঁজছিলাম তখন আমি এই থ্রেডটি পেয়েছি। যদিও আমি বুঝতে পেরেছি যে এটি একটি দেরি করে দেওয়া উত্তর, আমি ভেবেছিলাম এটি অন্য কারও পক্ষে কার্যকর হলে আমি এটিতে অবদান রাখব:
def find_dict_in_list(dicts, default=None, **kwargs):
"""Find first matching :obj:`dict` in :obj:`list`.
:param list dicts: List of dictionaries.
:param dict default: Optional. Default dictionary to return.
Defaults to `None`.
:param **kwargs: `key=value` pairs to match in :obj:`dict`.
:returns: First matching :obj:`dict` from `dicts`.
:rtype: dict
"""
rval = default
for d in dicts:
is_found = False
# Search for keys in dict.
for k, v in kwargs.items():
if d.get(k, None) == v:
is_found = True
else:
is_found = False
break
if is_found:
rval = d
break
return rval
if __name__ == '__main__':
# Tests
dicts = []
keys = 'spam eggs shrubbery knight'.split()
start = 0
for _ in range(4):
dct = {k: v for k, v in zip(keys, range(start, start+4))}
dicts.append(dct)
start += 4
# Find each dict based on 'spam' key only.
for x in range(len(dicts)):
spam = x*4
assert find_dict_in_list(dicts, spam=spam) == dicts[x]
# Find each dict based on 'spam' and 'shrubbery' keys.
for x in range(len(dicts)):
spam = x*4
assert find_dict_in_list(dicts, spam=spam, shrubbery=spam+2) == dicts[x]
# Search for one correct key, one incorrect key:
for x in range(len(dicts)):
spam = x*4
assert find_dict_in_list(dicts, spam=spam, shrubbery=spam+1) is None
# Search for non-existent dict.
for x in range(len(dicts)):
spam = x+100
assert find_dict_in_list(dicts, spam=spam) is None
এখানে প্রস্তাবিত বেশিরভাগ (সমস্ত না থাকলে) বাস্তবায়নের দুটি ত্রুটি রয়েছে:
একটি আপডেট প্রস্তাব:
def find_first_in_list(objects, **kwargs):
return next((obj for obj in objects if
len(set(obj.keys()).intersection(kwargs.keys())) > 0 and
all([obj[k] == v for k, v in kwargs.items() if k in obj.keys()])),
None)
সম্ভবত সর্বাধিক পাইথোনিক নয়, তবে কমপক্ষে আরও কিছুটা ফেইলসেফ।
ব্যবহার:
>>> obj1 = find_first_in_list(list_of_dict, name='Pam', age=7)
>>> obj2 = find_first_in_list(list_of_dict, name='Pam', age=27)
>>> obj3 = find_first_in_list(list_of_dict, name='Pam', address='nowhere')
>>>
>>> print(obj1, obj2, obj3)
{"name": "Pam", "age": 7}, None, {"name": "Pam", "age": 7}
সারকথা ।