【问题标题】:best way to trim an object to look like another object in python修剪对象以使其看起来像python中的另一个对象的最佳方法
【发布时间】:2017-06-08 11:07:26
【问题描述】:

假设我在 Python 中有两个对象(我会保持简单)

A = { "a" : { "b": 3, "c": 2 } }

B = { "a" : { "b": 7, "c": 4, "d": "howdy" } }

如果我想使用 A 作为 B 的模板,“修剪”对象 B 的最佳方法是什么,使其看起来像:

B = { "a" : { "b": 7, "c": 4 } }

在实践中,对象会更复杂(简单的数据类型但多级、列表、字典等)。

编辑:删除无意义的“Obj”以修复语法

【问题讨论】:

  • 对象是指字典吗?是否保证 obj B 与 obj B 具有相同的键?到目前为止,您尝试过什么?
  • 如果我使用您的简单示例回答,我担心不会回答您的问题。这些不是对象,它们是字典,而且您的声明不正确。
  • 创建 Obj C 并使用来自 Obj A 的键复制 Obj B 的元素 - 然后用 Obj C 代替 Obj B
  • 您是否必须处理任意级别的嵌套,还是总是只有 2 级?
  • @juanpa.arrivillaga 当然,但我的意思是这比 python 更像是 javascript 语法。

标签: python


【解决方案1】:

您可以为此使用递归函数:首先,检查模板的类型和原始的类型是否相同。如果是这样,你必须为不同的类型做不同的事情。例如,对于列表,您可以将原始列表减少到模板列表的长度,而对于字典,只保留模板中的键。在这两种情况下,请记住为这些列表或字典中包含的元素再次递归调用 trim 函数。

def trim(template, original):
    if type(template) != type(original):
        raise Exception("Types don't match")
    if isinstance(template, dict):
        # iterate keys and apply trim to values from orig dictionary
        return {k: trim(v, original[k]) for k, v in template.items()}
    elif isinstance(template, list):
        # zip lists and apply trim to pairs of templ and orig elements
        return [trim(t, o) for t, o in zip(template, original)]
    else:
        # atom: just return the original value
        return original

例子(注意我也把"c"的值改成了一个列表):

>>> A = { "a" : { "b": 3, "c": [4,5] } }
>>> B = { "a" : { "b": 7, "c": [8,9,10], "d": "howdy" } }
>>> trim(A, B)
{'a': {'b': 7, 'c': [8, 9]}}

【讨论】:

  • 好的,谢谢。它实际上更简单,因为我只需要限制“键”。我可能会考虑另一种方式——黑名单,而不是白名单。那就是将我的模板加载为 A = { "a" : [ "d" ] } 以表示应该排除 a.d(再次抱歉没有使用正确的 python 语法)。
  • @rottyguy “限制”键如何更简单?您如何将其推广到例如列表?
  • 不确定我是否完全理解您的问题。如果我只是限制键(在 B 中),我的模板 (A) 可能只包含键名。你不同意(如果是,你能举个例子吗?)
  • @rottyguy 我不能不同意,因为我不明白你的“模板”现在应该是什么样子。在您的问题中,您的模板只是另一个具有相同结构的字典,并且只是要保留的那些键。然后您将其更改为要删除的键的字典(尽管在您的示例中,您希望保留a,但删除d)。现在你想要一个带有键的字典来再次保留,但只有键?我提供了有效解决方案的原始问题有什么问题?
  • 啊,很抱歉造成混乱。我从“白名单”方法开始,使模板镜像输入字典(减去限制)。您通过遍历列表中的所有元素并拉出 B 而不是 A 中的键来解决。我现在想知道(大声)是否从“黑名单”pov 中接近它(在 A 中保留应该限制在 B 中的元素) 会更优雅/更容易吗? A = { "a" : ["d"] } 只是意味着在 B["a"]["d"] 处限制键。因此 A= { "a" : ["c","d"] } 在你的例子中会留下 B = { "a" : { "b" : 7 } } 。希望这是有道理的。
猜你喜欢
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 2010-12-04
  • 2016-09-18
  • 1970-01-01
  • 2019-07-19
相关资源
最近更新 更多