【问题标题】:Python list to XML and vice versaPython列表到XML,反之亦然
【发布时间】:2012-06-22 14:09:15
【问题描述】:

我编写了一些 Python 代码,用于将 Python 列表转换为 XML 元素。它用于与 LabVIEW 交互,因此是奇怪的 XML 数组格式。无论如何,这是代码:

def pack(data):
  # create the result element
  result = xml.Element("Array")

  # report the dimensions
  ref = data
  while isinstance(ref, list):
    xml.SubElement(result, "Dimsize").text = str(len(ref))
    ref = ref[0]

  # flatten the data
  while isinstance(data[0], list):
    data = sum(data, [])

  # pack the data
  for d in data:
    result.append(pack_simple(d))

  # return the result
  return result

现在我需要编写一个 unpack() 方法来将打包的 XML 数组转换回 python 列表。我可以很好地提取数组维度和数据:

def unpack(element):
  # retrieve the array dimensions and data
  lengths = []
  data = []
  for entry in element:
    if entry.text == "Dimsize":
      lengths.append(int(entry.text))

    else:
      data.append(unpack_simple(entry))

  # now what?

但我不确定如何展开数组。有什么有效的方法来做到这一点?

编辑:这是 python 列表和相应的 XML 的样子。注意:数组是 n 维的。

data = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

然后是 XML 版本:

<Array>
  <Dimsize>2</Dimsize>
  <Dimsize>2</Dimsize>
  <Dimsize>2</Dimsize>
  <I32>
    <Name />
    <Val>1</Val>
  </I32>

  ... 2, 3, 4, etc.
</Array>

但实际格式并不重要,我只是不知道如何从以下位置展开列表:

data = [1, 2, 3, 4, 5, 6, 7, 8]

回到:

data = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

给定:

lengths = [2, 2, 2]

假设 pack_simple() 和 unpack_simple() 对基本数据类型(int、long、string、boolean)执行相同的 pack() 和 unpack()。

【问题讨论】:

  • 数组是什么样子的? data 中有什么内容?
  • 一个更好的问题标题可能是“如何重塑扁平化的多维数组?”

标签: python xml labview


【解决方案1】:

尝试以下方法:

from operator import mul

def validate(array, sizes):
    if reduce(mul, sizes) != len(array):
        raise ValueError("Array dimension incompatible with desired sizes")

    return array, sizes

def reshape(array, sizes):
    for s in sizes:
        array = [array[i:i + s] for i in range(0, len(array), s)]

    return array[0]

data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
length = [2, 2, 3]

print reshape(validate(data, length))

length = [2, 2, 2]

print reshape(validate(data, length))

输出是:

[[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]]
Traceback:
   (...)
ValueError: Array dimension incompatible with desired sizes

另一种方法是使用numpy 数组。请注意,对于这个简单的任务,numpy 是一个相当大的依赖项,尽管您会发现大多数(常见)与数组相关的任务/问题已经在那里实现了:

from numpy import array

print array(data).reshape(*length)  # optionally add .tolist() to convert to list

编辑:添加数据验证

编辑:使用 numpy 数组的示例(感谢 J.F.Sebastian 的提示)

【讨论】:

  • Unode:哦,太好了,这也可以,而且我根本不需要更改代码。不幸的是,我已经接受了达人的回答。但我喜欢这个。现在为什么我不能想出这样的代码哈哈。
  • @root.ctrlc 如果它能更好地解决您的问题,您可以不接受我的回答并接受 Unodes。我认为你应该!
  • @Daren:哈哈,我不想成为一个混蛋。但是是的,他的稍微好一点:)
  • reshape() 可能是比transform() 更具体的名称。该参数可能称为array1d,而不是通用的array
  • 你是对的,只要数组通过validate() 函数,array1d 是不必要的。
【解决方案2】:

从里到外:

def group(seq, k):
    return [seq[i:i+k] for i in range(0, len(seq), k)]

unflattened = group(group(data, 2), 2)

如果您的尺寸不完全相同,您的示例可能会更简单。但我认为上面的代码应该可以工作。

【讨论】:

  • 达人:我现在就去试试。不过,我将不得不在每个维度的循环中调用 group()。
  • 达人:是的,做到了。一个小的变化,你只需要调用 group(group(data, 2), 2) 两次。是的,这个例子是次优的。此外,尺寸需要反转,即最里面的数字是文件中的最后一个尺寸。但这会起作用,谢谢。
  • 正确。啊!我讨厌把事情搞砸在我的脑海里。我将代码更新为只分组两次。
猜你喜欢
  • 1970-01-01
  • 2012-06-28
  • 2012-04-02
  • 1970-01-01
  • 2018-04-03
  • 2011-05-16
  • 2014-11-08
  • 2012-02-16
  • 2013-08-16
相关资源
最近更新 更多