অভিধানের মধ্যে মূল্য জেনে কী কী খুঁজে পাওয়ার কোনও সহজ উপায় আছে?
আমি যা ভাবতে পারি তা হ'ল:
key = [key for key, value in dict_obj.items() if value == 'value'][0]
অভিধানের মধ্যে মূল্য জেনে কী কী খুঁজে পাওয়ার কোনও সহজ উপায় আছে?
আমি যা ভাবতে পারি তা হ'ল:
key = [key for key, value in dict_obj.items() if value == 'value'][0]
iteritemsআমার জন্য ব্যবহার করছে না এটি 40x দ্রুত পার্থক্য করে ... (পূর্ববর্তী পদ্ধতি)
reverse_dictionary = {v:k for k,v in dictionary.items()}
উত্তর:
কেউ নেই. ভুলে যাবেন না যে মানটি 0 বা 1 এর বেশি সহ যে কোনও সংখ্যক কীতে পাওয়া যেতে পারে।
</sigh>
আপনার তালিকার উপলব্ধি সমস্ত ডিকের আইটেমগুলিতে সমস্ত মিল খুঁজে পাচ্ছে, তারপরে কেবল প্রথম কীটি ফিরিয়ে দেবে। এই জেনারেটরের এক্সপ্রেশনটি প্রথম মানটি ফেরত দেওয়ার জন্য কেবল যতটা প্রয়োজন পুনরাবৃত্তি করবে:
key = next(key for key, value in dd.items() if value == 'value')
ddডিক কোথায় বাড়াতে হবে StopIterationযদি কোনো মিল খুঁজে পাওয়া যায়, তাই আপনি যে ধরা ও মত একটি আরো উপযুক্ত ব্যতিক্রম আসতে চাইবেন ValueErrorবা KeyError।
keys = { key for key,value in dd.items() if value=='value' }বিভিন্ন ম্যাচ যদি সব কি সেট করুন।
এমন কেস রয়েছে যেখানে অভিধানের মধ্যে একটি থাকে: একটি ম্যাপিং
যেমন,
d = {1: "one", 2: "two" ...}
আপনার দৃষ্টিভঙ্গি ঠিক আছে যদি আপনি কেবল একক অনুসন্ধান করেন। তবে আপনার যদি একাধিক অনুসন্ধানের প্রয়োজন হয় তবে এটি একটি বিপরীত অভিধান তৈরি করা আরও দক্ষ
ivd = {v: k for k, v in d.items()}
যদি একই মান সহ একাধিক কীগুলির সম্ভাবনা থাকে তবে আপনাকে এক্ষেত্রে পছন্দসই আচরণ নির্দিষ্ট করতে হবে।
আপনার পাইথনটি যদি ২.6 বা তার বেশি হয় তবে আপনি এটি ব্যবহার করতে পারেন
ivd = dict((v, k) for k, v in d.items())
ivd=dict([(v,k) for (k,v) in d.items()])
invd = { v:k for k,v in d.items() }
এই সংস্করণটি আপনার চেয়ে 26% কম তবে অযৌক্তিক / অস্পষ্ট মানগুলির জন্যও একইভাবে কাজ করে (প্রথম ম্যাচটি ফেরত দেয়, যেমনটি আপনার মত হয়)। তবে এটি সম্ভবত আপনার দ্বিগুণ ধীর, কারণ এটি দু'বার ডিক থেকে একটি তালিকা তৈরি করে।
key = dict_obj.keys()[dict_obj.values().index(value)]
অথবা আপনি যদি পঠনযোগ্যতার চেয়ে ব্রিভিটি পছন্দ করেন তবে এর সাথে আরও একটি চরিত্র সংরক্ষণ করতে পারবেন
key = list(dict_obj)[dict_obj.values().index(value)]
এবং যদি আপনি দক্ষতা পছন্দ করেন তবে @ পলমিসিগুইয়ারের পদ্ধতির আরও ভাল। যদি এমন অনেকগুলি কী থাকে যা একই মানটি ভাগ করে দেয় তবে কীগুলির তালিকাকে তালিকা বোঝার সাহায্যে ইনস্ট্যান্ট না করা এবং এর পরিবর্তে একটি জেনারেটর ব্যবহার না করা আরও দক্ষ:
key = (key for key, value in dict_obj.items() if value == 'value').next()
dict.keys()এবং dict.values()যতক্ষণ dictনা কলগুলির মধ্যে রূপান্তরিত হয় না ততক্ষণ তার সাথে যোগাযোগ করার নিশ্চয়তা দেওয়া হয় ।
যেহেতু এটি এখনও খুব প্রাসঙ্গিক, প্রথম গুগল হিট হয়েছে এবং আমি এটি সন্ধানের জন্য কিছুটা সময় ব্যয় করেছি, আমি আমার (পাইথন 3 এ কাজ করা) সমাধান পোস্ট করব:
testdict = {'one' : '1',
'two' : '2',
'three' : '3',
'four' : '4'
}
value = '2'
[key for key in testdict.items() if key[1] == value][0][0]
Out[1]: 'two'
এটি আপনাকে মিলবে প্রথম মানটি।
DoubleDictনীচে নীচে যেমন অভিধানের মতো ক্লাসটি আপনি চান তা কি? আপনি সরবরাহিত মেটাচ্লাসগুলির মধ্যে যে কোনও একটি ব্যবহার করে ব্যবহার করতে পারেন DoubleDictবা কোনও মেটাক্লাস ব্যবহার করা এড়াতে পারেন।
import functools
import threading
################################################################################
class _DDChecker(type):
def __new__(cls, name, bases, classdict):
for key, value in classdict.items():
if key not in {'__new__', '__slots__', '_DoubleDict__dict_view'}:
classdict[key] = cls._wrap(value)
return super().__new__(cls, name, bases, classdict)
@staticmethod
def _wrap(function):
@functools.wraps(function)
def check(self, *args, **kwargs):
value = function(self, *args, **kwargs)
if self._DoubleDict__forward != \
dict(map(reversed, self._DoubleDict__reverse.items())):
raise RuntimeError('Forward & Reverse are not equivalent!')
return value
return check
################################################################################
class _DDAtomic(_DDChecker):
def __new__(cls, name, bases, classdict):
if not bases:
classdict['__slots__'] += ('_DDAtomic__mutex',)
classdict['__new__'] = cls._atomic_new
return super().__new__(cls, name, bases, classdict)
@staticmethod
def _atomic_new(cls, iterable=(), **pairs):
instance = object.__new__(cls, iterable, **pairs)
instance.__mutex = threading.RLock()
instance.clear()
return instance
@staticmethod
def _wrap(function):
@functools.wraps(function)
def atomic(self, *args, **kwargs):
with self.__mutex:
return function(self, *args, **kwargs)
return atomic
################################################################################
class _DDAtomicChecker(_DDAtomic):
@staticmethod
def _wrap(function):
return _DDAtomic._wrap(_DDChecker._wrap(function))
################################################################################
class DoubleDict(metaclass=_DDAtomicChecker):
__slots__ = '__forward', '__reverse'
def __new__(cls, iterable=(), **pairs):
instance = super().__new__(cls, iterable, **pairs)
instance.clear()
return instance
def __init__(self, iterable=(), **pairs):
self.update(iterable, **pairs)
########################################################################
def __repr__(self):
return repr(self.__forward)
def __lt__(self, other):
return self.__forward < other
def __le__(self, other):
return self.__forward <= other
def __eq__(self, other):
return self.__forward == other
def __ne__(self, other):
return self.__forward != other
def __gt__(self, other):
return self.__forward > other
def __ge__(self, other):
return self.__forward >= other
def __len__(self):
return len(self.__forward)
def __getitem__(self, key):
if key in self:
return self.__forward[key]
return self.__missing_key(key)
def __setitem__(self, key, value):
if self.in_values(value):
del self[self.get_key(value)]
self.__set_key_value(key, value)
return value
def __delitem__(self, key):
self.pop(key)
def __iter__(self):
return iter(self.__forward)
def __contains__(self, key):
return key in self.__forward
########################################################################
def clear(self):
self.__forward = {}
self.__reverse = {}
def copy(self):
return self.__class__(self.items())
def del_value(self, value):
self.pop_key(value)
def get(self, key, default=None):
return self[key] if key in self else default
def get_key(self, value):
if self.in_values(value):
return self.__reverse[value]
return self.__missing_value(value)
def get_key_default(self, value, default=None):
return self.get_key(value) if self.in_values(value) else default
def in_values(self, value):
return value in self.__reverse
def items(self):
return self.__dict_view('items', ((key, self[key]) for key in self))
def iter_values(self):
return iter(self.__reverse)
def keys(self):
return self.__dict_view('keys', self.__forward)
def pop(self, key, *default):
if len(default) > 1:
raise TypeError('too many arguments')
if key in self:
value = self[key]
self.__del_key_value(key, value)
return value
if default:
return default[0]
raise KeyError(key)
def pop_key(self, value, *default):
if len(default) > 1:
raise TypeError('too many arguments')
if self.in_values(value):
key = self.get_key(value)
self.__del_key_value(key, value)
return key
if default:
return default[0]
raise KeyError(value)
def popitem(self):
try:
key = next(iter(self))
except StopIteration:
raise KeyError('popitem(): dictionary is empty')
return key, self.pop(key)
def set_key(self, value, key):
if key in self:
self.del_value(self[key])
self.__set_key_value(key, value)
return key
def setdefault(self, key, default=None):
if key not in self:
self[key] = default
return self[key]
def setdefault_key(self, value, default=None):
if not self.in_values(value):
self.set_key(value, default)
return self.get_key(value)
def update(self, iterable=(), **pairs):
for key, value in (((key, iterable[key]) for key in iterable.keys())
if hasattr(iterable, 'keys') else iterable):
self[key] = value
for key, value in pairs.items():
self[key] = value
def values(self):
return self.__dict_view('values', self.__reverse)
########################################################################
def __missing_key(self, key):
if hasattr(self.__class__, '__missing__'):
return self.__missing__(key)
if not hasattr(self, 'default_factory') \
or self.default_factory is None:
raise KeyError(key)
return self.__setitem__(key, self.default_factory())
def __missing_value(self, value):
if hasattr(self.__class__, '__missing_value__'):
return self.__missing_value__(value)
if not hasattr(self, 'default_key_factory') \
or self.default_key_factory is None:
raise KeyError(value)
return self.set_key(value, self.default_key_factory())
def __set_key_value(self, key, value):
self.__forward[key] = value
self.__reverse[value] = key
def __del_key_value(self, key, value):
del self.__forward[key]
del self.__reverse[value]
########################################################################
class __dict_view(frozenset):
__slots__ = '__name'
def __new__(cls, name, iterable=()):
instance = super().__new__(cls, iterable)
instance.__name = name
return instance
def __repr__(self):
return 'dict_{}({})'.format(self.__name, list(self))
না, আপনি সমস্ত কীগুলি না দেখে এবং তাদের সমস্ত মান পরীক্ষা না করে দক্ষতার সাথে এটি করতে পারবেন না। সুতরাং এটি O(n)করার জন্য আপনার সময় প্রয়োজন । যদি আপনাকে এরকম অনেকগুলি অনুসন্ধানের প্রয়োজন হয় তবে আপনাকে বিপরীত অভিধান তৈরি করে দক্ষতার সাথে এটি করতে হবে (এছাড়াও এটিও করা যেতে পারে O(n)) এবং তারপরে এই বিপরীত অভিধানের ভিতরে একটি অনুসন্ধান তৈরি করতে হবে (প্রতিটি অনুসন্ধান গড়ে গড়ে নেওয়া হবে O(1))।
এখানে একটি সাধারণ অভিধান থেকে কীভাবে বিপরীত অভিধানটি তৈরি করা যায় (যা একাধিক ম্যাপিং করতে সক্ষম হবে):
for i in h_normal:
for j in h_normal[i]:
if j not in h_reversed:
h_reversed[j] = set([i])
else:
h_reversed[j].add(i)
উদাহরণস্বরূপ যদি আপনার
h_normal = {
1: set([3]),
2: set([5, 7]),
3: set([]),
4: set([7]),
5: set([1, 4]),
6: set([1, 7]),
7: set([1]),
8: set([2, 5, 6])
}
আপনার h_reversedহবে
{
1: set([5, 6, 7]),
2: set([8]),
3: set([1]),
4: set([5]),
5: set([8, 2]),
6: set([8]),
7: set([2, 4, 6])
}
আমার জানা মতে একটি উপায় নেই, তবে এটি করার একটি উপায় হ'ল কী অনুসারে সাধারণ অনুসন্ধানের জন্য একটি ডিক তৈরি করা এবং মান অনুসারে বিপরীত অনুসন্ধানের জন্য অন্য একটি ডিক তৈরি করা।
এখানে এ জাতীয় বাস্তবায়নের উদাহরণ রয়েছে:
http://code.activestate.com/recips/415903-two-dict-classes- which-can-lookup-keys-by-value-an/
এর অর্থ এই যে কোনও মানটির জন্য কীগুলি অনুসন্ধান করার ফলে একাধিক ফলাফল হতে পারে যা সাধারণ তালিকা হিসাবে ফিরে পাওয়া যায়।
আমি জানি এটি 'অপ্রয়োজনীয়' হিসাবে বিবেচিত হতে পারে তবে এই দৃশ্যে আমি প্রায়শই মান রেকর্ডে একটি অতিরিক্ত কলাম হিসাবে কীটি সঞ্চয় করি:
d = {'key1' : ('key1', val, val...), 'key2' : ('key2', val, val...) }
এটি একটি ট্রেডঅফ এবং ভুল অনুভব করে তবে এটি সহজ এবং কাজ করে এবং অবশ্যই সাধারণ মূল্যবোধের পরিবর্তে মানগুলি দ্বিগুণ হওয়ার উপর নির্ভর করে।
reverse_dictionary = {v:k for k,v in dictionary.items()}
আপনার যদি অনেকগুলি বিপরীত লুকআপ করতে হয়
অভিধানের মানগুলির মাধ্যমে যে কোনও ধরণের বিষয় হতে পারে সেগুলি হ্যাশ বা অন্যভাবে সূচিকৃত হতে পারে না। সুতরাং মান দ্বারা কী সন্ধান করা এই সংগ্রহের ধরণের জন্য অপ্রাকৃত। এর মতো যে কোনও প্রশ্ন কেবল ও (এন) সময়ে কার্যকর করা যায়। সুতরাং এটি যদি প্রায়শই কাজ হয়ে থাকে তবে আপনার জোন সুজেস্টেড বা সম্ভবত কিছু স্থানিক সূচক (ডিবি বা http://pypi.python.org/pypi/Rtree/ ) এর মতো কীগুলির কিছু সূচীকরণের জন্য নজর নেওয়া উচিত ।
আমি অভিধানগুলিকে এক ধরণের "ডাটাবেস" হিসাবে ব্যবহার করছি তাই আমার একটি চাবি খুঁজে বার করতে হবে যা আমি পুনরায় ব্যবহার করতে পারি। আমার ক্ষেত্রে, যদি কোনও কীটির মান হয় None, তবে আমি অন্য আইডি "বরাদ্দ" না করে এটিকে নিতে এবং পুনরায় ব্যবহার করতে পারি। আমি এখন ভাগ করে নিলাম।
db = {0:[], 1:[], ..., 5:None, 11:None, 19:[], ...}
keys_to_reallocate = [None]
allocate.extend(i for i in db.iterkeys() if db[i] is None)
free_id = keys_to_reallocate[-1]
আমি এই এক মত, কারণ আমি চেষ্টা এবং যেমন কোনো ত্রুটি ধরা হবে না StopIterationবা IndexError। যদি কোনও কী উপলব্ধ free_idথাকে তবে তার মধ্যে একটি থাকবে। যদি সেখানে না থাকে, তবে এটি সহজভাবে হবে None। সম্ভবত অজগর নয়, তবে আমি সত্যিই tryএখানে একটি ব্যবহার করতে চাইনি ...