【问题标题】:Replace None in a python dictionary在python字典中替换None
【发布时间】:2016-06-29 09:30:15
【问题描述】:

我碰巧有一本复杂的字典(有列表、列表中的字典等)。一些键的值设置为 None

有没有办法可以用我自己的一些默认值替换这个 None,而不管字典的复杂结构如何?

【问题讨论】:

  • 你也想替换嵌套字典中的None吗?
  • 是的,但据我所知,没有捷径可走,您必须遍历 dict 以及其中的任何容器值,随时替换 Nones。这听起来像是递归的好工作。
  • @MariusSiuram:OP 想要替换 values 是 None,而不是键。
  • @Marius:不,他的意思是,“某些值”是“某些键的值”:)
  • 或者,或者,您对以下数据结构有何期望:{1: 'one', 2: [1, 2, None], '3': None, None: {None: None, 2: [1,2, None, {None: None, 2: None}]}}

标签: python json dictionary nonetype


【解决方案1】:

来自 Lutz 的递归解决方案:

def replace(any_dict):
    for k, v in any_dict.items():
        if v is None:
            any_dict[k] = "my default value"
        elif type(v) == type(any_dict):
            replace(v)

replace(my_dict)

【讨论】:

  • 什么是“elif type(v) == type(any_dict): replace(v)”部分?听起来没什么用。
【解决方案2】:
# replace_none_with_empty_str_in_dict.py

raw = {'place': 'coffee shop', 'time': 'noon', 'day': None}

def replace_none_with_empty_str(some_dict):
    return { k: ('' if v is None else v) for k, v in some_dict.items() }

print(replace_none_with_empty_str(raw))

【讨论】:

  • 用 Python 3.5.3 测试
【解决方案3】:

这是一个递归解决方案,它也替换了列表中的Nones。

首先我们定义一个简单的类Null,作为None的替代品。

class Null(object):
    def __repr__(self):
        return 'Null'

NULL = Null()

def replace_none(data):
    for k, v in data.items() if isinstance(data, dict) else enumerate(data):
        if v is None:
            data[k] = NULL
        elif isinstance(v, (dict, list)):
            replace_none(v)

# Test
data = {
    1: 'one', 
    2: ['two', 2, None], 
    3: None, 
    4: {4: None, 44: 'four'},
    5:  {
            5: [55, 56, None], 
            6: {66: None, 67: None},
            8: [88, {9:'nine', 99:None}, 100]
        }
}

print(data)
replace_none(data)
print(data)

输出

{1: 'one', 2: ['two', 2, None], 3: None, 4: {44: 'four', 4: None}, 5: {8: [88, {9: 'nine', 99: None}, 100], 5: [55, 56, None], 6: {66: None, 67: None}}}
{1: 'one', 2: ['two', 2, Null], 3: Null, 4: {44: 'four', 4: Null}, 5: {8: [88, {9: 'nine', 99: Null}, 100], 5: [55, 56, Null], 6: {66: Null, 67: Null}}}

【讨论】:

    【解决方案4】:

    您可以使用遍历所有字典和列表的递归函数来做到这一点:

    def convert(obj):
        if type(obj) == list:
            for x in obj:
                convert(x)
        elif type(obj) == dict:
            for k, v in obj.iteritems():
                if v is None:
                    obj[k] = 'DEFAULT'
                else:
                    convert(v)
    
    data = {1: 'foo', 2: None, 3: [{1: 'foo', 2: None}]}
    convert(data)
    print data # -> {1: 'foo', 2: 'DEFAULT', 3: [{1: 'foo', 2: 'DEFAULT'}]}
    

    【讨论】:

      【解决方案5】:

      您可以使用 object_pairs_hook 来自 json 模块:

      def dict_clean(items):
          result = {}
          for key, value in items:
              if value is None:
                  value = 'default'
              result[key] = value
          return result
      
      dict_str = json.dumps(my_dict)
      my_dict = json.loads(dict_str, object_pairs_hook=dict_clean)
      

      【讨论】:

      • 函数的替代实现:return {k: v if v is not None else 'default' for k, v in items}.
      • 我还会为dict_clean 函数添加一个default 参数。
      • 不确定是否最佳,但绝对非常优雅。但是,如果 dict 包含任何不可序列化的对象,这可能会失败。
      【解决方案6】:
      for k, v in my_dict.items():
          if v is None:
              my_dict[k] = "my default value"
      

      【讨论】:

      • 关于None 的问题似乎很明确,所以我应该建议v is None 而不是not v,因为最后一个选项会更改空字符串、错误值、数字0...跨度>
      • 同意,None 小于 not v。
      • @LutzHorn 如果该值位于第一级,该解决方案将起作用。在我的情况下,该值在 dict 内部(在 dict 列表中的 dict 内部)并且解决方案失败
      • 请编辑您的问题并提供您的真实输入示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-23
      • 2013-11-15
      • 1970-01-01
      • 2018-11-16
      • 2020-01-23
      • 1970-01-01
      • 2019-03-16
      相关资源
      最近更新 更多