如何在Python中检查嵌套字典是否具有特定类型的值?

huangapple go评论59阅读模式
英文:

How do I check if nested dictionary has a value of a specific type in Python?

问题

我想知道如何检查一个包含键值对的字典,其中值可以是任何包含自定义对象的 Python 类型。

假设对象称为 MyObject,我有一个字典。

{
   "test1": MyObject(),
   "test2": [MyObject(), MyObject()],
   "test3": {"some_key": MyObject()},
   "test4": {"some_key": [MyObject()]},
   "test5": (MyObject(), MyObject()),  # 元组
   "test6": {MyObject(), MyObject()},  # 集合
   "test7": {"some_key1": {"some_key2": {"some_key3": MyObject()}}},
   ....
}

我想要检查这些值中是否有包含我的自定义对象的实例。这可能吗?

我尝试过以下方法:

def contains_object(d):
   for k, v in d.items():
      if isinstance(v, MyObject):
         return True
      elif isinstance(v, (list, set, tuple)):
         for i in v:
            if isinstance(i, MyObject):
               return True
      elif isinstance(v, dict):
         for a, b in v.items():
            if isinstance(b, MyObject):
               return True
   return False

如何简化上述解决方案?它应该返回一个布尔值,表示字典中是否有任何包含 MyObject 的值。

英文:

I want to know how I can check if a dictionary with key-value pairs, where the values can be of any python type that contains my custom object.

Lets say object is called MyObject and I have a dictionary.

{
   "test1": MyObject()
   "test2": [MyObject(), MyObject()]
   "test3": {"some_key": MyObject()]
   "test4": {"some_key": [MyObject()]
   "test5": (MyObject(), MyObject()) # tuple
   "test6": {MyObject(), MyObject()} # set
   "test7": {"some_key1": {"some_key2": {"some_key3": MyObject()}}}
   ....
}

I want to be able to check if any of these values are or contain an instance of my custom object. Is this possible?

I Have tried:

def contains_object(d):
   for k,v in d.items():
      if isinstance(v, MyObject):
         return True
      elif isinstance(v, (list, set, tuple)):
         for i in v:
            if isinstance(i, MyObject):
               return True
      elif isinstance(v, dict):
         for a, b in v.items():
            if isinstance(b, MyObject):
               return True
   return False

How do I simplify the above solution. It should return a boolean for whether or not the dictionary has any value that contains MyObject.

答案1

得分: 2

以下是翻译好的内容:

在大多数情况下,这样的代码应该能够工作,或者至少作为进一步扩展的良好起点。它基于评论中建议的简单递归。

def contains_target_type(element, target_type):
    if isinstance(element, target_type):
        return True
    elif isinstance(element, dict):
        for value in element.values():
            if contains_target_type(value, target_type):
                return True
    elif isinstance(element, (list, set, tuple)):
        for value in element:
            if contains_target_type(value, target_type):
                return True
    return False

你可以这样调用它:

target_type = MyObject
flag = contains_target_type(dict_test_data, target_type)
英文:

Something like this should work in most cases or at least serve as a good starting point for further expansion. It is based on simple recursion as suggested in the comments

def contains_target_type(element, target_type):
    if isinstance(element, target_type):
        return True
    elif isinstance(element, dict):
        for value in element.values():
            if contains_target_type(value, target_type):
                return True
    elif isinstance(element, (list, set, tuple)):
        for value in element:
            if contains_target_type(value, target_type):
                return True
    return False

You can call it like:

target_type = MyObject
flag = contains_target_type(dict_test_data, target_type)

答案2

得分: 0

你需要一个递归的方法来遍历字典中的任何可能嵌套。

以下代码可以实现这一功能。它将打印与匹配自定义类的值相关联的键。如果自定义类实例在可迭代对象中,相关联的键只会报告一次。

class MyObject:
    ...


_dict = {
   "test1": MyObject(),
   "test2": [MyObject(), MyObject()],
   "test3": {"some_key": MyObject()},
   "test4": {"some_key": [MyObject()]},
   "test5": (MyObject(), MyObject()),
   "test6": {MyObject(), MyObject()},
   "test7": {"some_key1": {"some_key2": {"some_key3": MyObject()}}}
}

def parse(d):
    key = None
    def _parse(d):
        nonlocal key
        if isinstance(d, MyObject):
            print(key)
            return True
        if isinstance(d, dict):
            for key, v in d.items():
                _parse(v)
        elif isinstance(d, (list, set, tuple)):
            for v in d:
                if _parse(v) is True:
                    break
    _parse(d)

parse(_dict)

输出:

test1
test2
some_key
some_key
test5
test6
some_key3
英文:

You need a recursive approach that allows you to navigate any possible nesting within your dictionary.

The following code will do that. It will print the key that's associated with the value matching the custom class. If the custom class instance is within an iterable, the associated key will only be reported once.

class MyObject:
    ...


_dict = {
   "test1": MyObject(),
   "test2": [MyObject(), MyObject()],
   "test3": {"some_key": MyObject()},
   "test4": {"some_key": [MyObject()]},
   "test5": (MyObject(), MyObject()),
   "test6": {MyObject(), MyObject()},
   "test7": {"some_key1": {"some_key2": {"some_key3": MyObject()}}}
}

def parse(d):
    key = None
    def _parse(d):
        nonlocal key
        if isinstance(d, MyObject):
            print(key)
            return True
        if isinstance(d, dict):
            for key, v in d.items():
                _parse(v)
        elif isinstance(d, (list, set, tuple)):
            for v in d:
                if _parse(v) is True:
                    break
    _parse(d)

parse(_dict)

Output:

test1
test2
some_key
some_key
test5
test6
some_key3

答案3

得分: 0

你可以简化代码,像这样:

def check_for_custom_object(data):
    if isinstance(data, MyObject):
        # 对MyObject进行处理
    
    elif isinstance(data, (list, set, tuple)):
        for item in data:
            check_for_custom_object(item)
        
    elif isinstance(data, dict):
        for value in data.values():
            check_for_custom_object(value)
英文:

You can simplify the code such like this:

def check_for_custom_object(data):
    if isinstance(data, MyObject):
        # do something with MyObject
    
    elif isinstance(data, (list, set, tuple)):
        for item in data:
            check_for_custom_object(item)
        
    elif isinstance(data, dict):
        for value in data.values():
            check_for_custom_object(value)

huangapple
  • 本文由 发表于 2023年8月9日 16:58:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定