【问题标题】:dictionary insert default value if empty字典如果为空则插入默认值
【发布时间】:2019-03-09 00:50:11
【问题描述】:

我正在从 xml 文件创建字典,如下所示:

for edge in root.findall('n:graph/n:edge', ns):
        source = edge.get('source')
        target = edge.get('target')
        edges[(source, target)] = tuple([data.text for data in edge if \
        (data.get('key') == keys[0] or data.get('key') == keys[1])])

这给了我这样的输出:

{ ('4893468839', '977369380') : ('名称', '长度') ... }

当字段 name 的值为空时,有没有办法可以输入默认文本“noName”?所有的键都有一个长度值,但不是所有的都有一个名字,所以我想避免这样的输出:

{ ('4893468839', '977369380') : ('长度', ) ... }

在这种情况下得到这样的东西:

{ ( '4893468839', '977369380' ) : ('noName' , 'length' ) ... }

更多详细信息:

from lxml import etree
    class graph():
        _path = ""
    def _readFile(self):
            data = etree.parse(self._path)
            root = data.getroot()
    for edge in root.findall('n:graph/n:edge', ns):
                source = edge.get('source')
                target = edge.get('target')
                edges[(source, target)] = tuple([data.text for data in edge if data.get('key') in keys[:2]])

给定一段xml,如下所示:

<key attr.name="ref" attr.type="string" for="edge" id="d14" />
<key attr.name="name" attr.type="string" for="edge" id="d13" />
<key attr.name="geometry" attr.type="string" for="edge" id="d12" />
<key attr.name="length" attr.type="string" for="edge" id="d11" />
<key attr.name="oneway" attr.type="string" for="edge" id="d10" />
<key attr.name="highway" attr.type="string" for="edge" id="d9" />
<key attr.name="bridge" attr.type="string" for="edge" id="d8" />
<key attr.name="osmid" attr.type="string" for="edge" id="d7" />

<edge id="0" source="4331489627" target="4331489577">
  <data key="d7">435211336</data>
  <data key="d13">Calle Carretera</data>
  <data key="d9">residential</data>
  <data key="d10">False</data>
  <data key="d11">52.45</data>
  <data key="d12">LINESTRING (-4.8413613 39.4799045, -4.8414814 39.4798489, -4.8419449 39.4797838)</data>
</edge>

将生成以下输出我没问题:

{ ('4331489627', '4331489577') : ('Calle Carretera', '52.45') }

但是例如有一些边缘,像这样缺少名称或d13键标签:

<edge id="0" source="982621562" target="946409159">
      <data key="d7">483537143</data>
      <data key="d14">CM-4106</data>
      <data key="d9">secondary</data>
      <data key="d10">False</data>
      <data key="d11">104.66499999999999</data>
      <data key="d12">LINESTRING (-4.8366071 39.4783468, -4.8368979 39.4789602, -4.8371678 39.4791592)</data>
    </edge>

在这些情况下,由于找不到标签文本,我得到了这个输出:

{ ('982621562', '946409159') : ('52.45', ) }

如果可能的话,希望得到类似的东西:

{ ('982621562', '946409159') : ('noName', '52.45') }

【问题讨论】:

  • 你尝试过类似data.text or 'noName' for data in edge if data.get('key') in keys[:2]的方法吗?
  • @SamMason 刚刚尝试过,但似乎在没有打印默认值的情况下做了同样的事情。边缘有几个键,但其中一些缺少它,在这种情况下,我想放置默认值
  • 你能发布一个更完整的例子吗?例如,包括一些显示问题的 xml、包导入、大概像 ET.fromstring(data) 这样的调用等
  • 啊,你之前发的不是这个!你有一个逗号用于在不同的地方丢失数据,这表明正在发生完全不同的事情。请直接复制/粘贴输出,因为这样的细微差别很重要,并提供有关正在发生的事情的信息
  • 没有问题,都是学习经验的一部分!

标签: python dictionary key default-value is-empty


【解决方案1】:

基于以上,我整理了一个实际可行的示例:

from lxml import etree

root = etree.fromstring("""
<xml><graph>
<key attr.name="ref" attr.type="string" for="edge" id="d14" />
<key attr.name="name" attr.type="string" for="edge" id="d13" />
<key attr.name="geometry" attr.type="string" for="edge" id="d12" />
<key attr.name="length" attr.type="string" for="edge" id="d11" />
<key attr.name="oneway" attr.type="string" for="edge" id="d10" />
<key attr.name="highway" attr.type="string" for="edge" id="d9" />
<key attr.name="bridge" attr.type="string" for="edge" id="d8" />
<key attr.name="osmid" attr.type="string" for="edge" id="d7" />
<edge id="0" source="4331489627" target="4331489577">
  <data key="d7">435211336</data>
  <data key="d13">Calle Carretera</data>
  <data key="d9">residential</data>
  <data key="d10">False</data>
  <data key="d11">52.45</data>
  <data key="d12">LINESTRING (-4.8413613 39.4799045, -4.8414814 39.4798489, -4.8419449 39.4797838)</data>
</edge>
<edge id="0" source="982621562" target="946409159">
  <data key="d7">483537143</data>
  <data key="d14">CM-4106</data>
  <data key="d9">secondary</data>
  <data key="d10">False</data>
  <data key="d11">104.66499999999999</data>
  <data key="d12">LINESTRING (-4.8366071 39.4783468, -4.8368979 39.4789602, -4.8371678 39.4791592)</data>
</edge>
</graph></xml>
""")

keys = {}
for key in root.findall('graph/key'):
  keys[key.get('attr.name')] = key.get('id')

key_name = keys['name']
key_length = keys['length']

out = {}
for edge in root.findall('graph/edge'):
  data = dict((d.get('key'), d.text) for d in edge.findall('data'))
  value = (data.get(key_name, 'noName'), data[key_length])
  out[(edge.get('source'), edge.get('target'))] = value

print(out)

请注意,您现在获得了第二条边的 None。在它“丢失”之前,因为您告诉它要被过滤掉。相反,我的代码基于 xml 创建一个字典,然后始终使用包含两个元素的元组填充 out 中的值。

【讨论】:

  • 非常感谢!已经通过创建“辅助”字典来存储所有键值然后获取信息将其放入另一个来解决它。有问题吗,在我的代码中,我根据解析的 xml 文件过滤原因,d13 可能是另一个键,例如 d12 所以我通过读取文件的请求来创建一个列表以查找具有 attr 的那些键.name="name" 或我感兴趣的长度
  • 有什么方法可以做类似的事情吗?现在我得到了我想要的输出,但只针对那些以 d13 和 d11 为键的文件,但它们可能会改变。在主帖中,我添加了 xml 部分,其中键的“索引”与 attr.names 我正在谈论
  • 干杯,非常感谢您的帮助,非常感谢! :D ps: 刚刚意识到有两个键叫做'name' 我想我得想办法区分它们哈哈
  • 在 dict 的每个键中也存储了 'for' 属性,然后将它们作为 key_name = keys[('name', 'edge')] 查找,避免使用其他名称标签用于图表。
猜你喜欢
  • 2012-12-01
  • 2017-12-25
  • 2020-01-02
  • 1970-01-01
  • 2016-01-31
  • 2021-08-27
  • 2020-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多