Python 列表列表中层次结构的非规范化

Python 列表列表中层次结构的非规范化,python,python-2.7,Python,Python 2.7,我正在解析一个文件,其中标签定义如下,层次结构使用新行表示 +--------------------+--------------------+--------------------+ | L1 - A | | | | | L2 - B | | | |

我正在解析一个文件,其中标签定义如下,层次结构使用新行表示

+--------------------+--------------------+--------------------+
| L1 - A             |                    |                    |
|                    |  L2 - B            |                    |
|                    |                    |  L3 - C            |
|                    |                    |                    |
| L1 - D             |                    |                    |
|                    |  L2 - E            |                    |
|                    |                    |  L3 - F            |
+--------------------+--------------------+--------------------+
本人将上述情况表述为:

labels = [
   ['A', None, None, None, 'D', None, None],
   [None, 'B', None, None, None, 'E', None],
   [None, None, 'C', None, None, None, 'F']
]
我试过了

def joinfoo(items):
   if len(items) == 1:
      return items[0]

   result = []
   active = None
   for x, y in zip(items[0], joinfoo(items[1:])):
      active = x if x else active
      if type(y) is tuple:
         result.append((active, y[0], y[1]))
      else:
         result.append((active, y))

   return result
我想要

[
   ('A', None, None), ('A', 'B', None), ('A', 'B', 'C'),
   (None, None, None),
   ('D', None, None), ('D', 'E', None), ('D', 'E', 'F')
]
还有这个

[
   ('A', None, None), ('A', 'B', None), ('A', 'B', 'C'),
   ('A', 'B', None),
   ('D', 'B', None), ('D', 'E', None), ('D', 'E', 'F')
]
关于如何修复
joinfoo()
以获得所需结果的建议?解决方案需要支持可变数量的列

对于zip中的x,y(joinfoo(items[:-1]),items[-1]):而不是zip中的x,y(items[0]),joinfoo(items[1:]):要朝正确的方向走

编辑: 列表的原始列表可能错误地暗示了层次结构的模式。没有定义的模式。列数也是可变的。一个更好的测试用例可能

+--------------+--------------+--------------+
|   L1 - A     |              |              |    = A
|              |    L2 - B    |              |    = A - B
|              |              |    L3 - C    |    = A - B - C
|              |              |    L3 - D    |    = A - B - D
|              |    L2 - E    |              |    = A - E
|              |              |              |    =   
|   L1 - F     |              |              |    = F
|              |    L2 - G    |              |    = F - G
|              |              |    L3 - H    |    = F - G - H
+--------------+--------------+--------------+

labels = [
   ['A', None, None, None, None, None, 'F', None, None],
   [None, 'B', None, None, 'E', None, None, 'G', None],
   [None, None, 'C', 'D', None, None, None, None, 'H']
]

以下是joinfoo的一个版本,它提供了您想要的:

def empty(item):  # added this function
   if item is None:
      return True
   else:
      return not any(item)


def joinfoo(items):
   if len(items) == 1:
      return items[0]

   result = []
   active = None
   y_last = None  # added this
   for x, y in zip(items[0], joinfoo(items[1:])):
      active = x if x else active
      if not empty(y_last) and empty(y):  # added this if statement
         active = None
      y_last = y  # added this
      if type(y) is tuple:
         result.append((active, y[0], y[1]))
      else:
         result.append((active, y))

   return result
每次y条目切换回无时,您也希望“活动”切换回无

顺便说一句,正如joinfoo所写的那样,它不适合加入超过3个列表。如果你需要的话


替换
result.append((活动,y[0],y[1]))
result.append((活动,*y))
我手头有点时间,想知道我会如何解决这个问题

这是我的解决方案,也许它能激发一些想法:

labels = """\
+--------------------+--------------------+--------------------+
| L1 - A             |                    |                    |
|                    |  L2 - B            |                    |
|                    |                    |  L3 - C            |
|                    |                    |                    |
| L1 - D             |                    |                    |
|                    |  L2 - E            |                    |
|                    |                    |  L3 - F            |
+--------------------+--------------------+--------------------+
"""

lines = [[(s.strip()[-1:] if s.strip() else None)
             for s in line[1:-1].split('|')]
                 for line in labels.splitlines()[1:-1]]

for index, labels in enumerate(lines):
    if not any(labels):
        continue
    for i, label in enumerate(labels):
        if label:
            break
        if not label:
            lines[index][i] = lines[index-1][i]

print([tuple(labels) for labels in lines])

# --> [('A', None, None), ('A', 'B', None), ('A', 'B', 'C'), (None, None, None), ('D', None, None), ('D', 'E', None), ('D', 'E', 'F')]

active=x if x else active
从这一行开始,如果x为None,则保持active的原始值,但是,检查所需的输出时,如果达到元组的计数,则需要一种将active重置为None的方法

以下是我如何实现您期望的输出

def joinfoo(items):
   if len(items) == 1:
      return items[0]

   result = []
   active_counter=0
   count=0
   active = None
   for x, y in zip(items[0], joinfoo(items[1:])):
      count=len(y) if type(y) is tuple else 0
      if active_counter >count:
          active_counter=0
          active=None
      else:
          active_counter +=1

      active = x if x else active
      if type(y) is tuple:
         result.append((active, y[0], y[1]))
      else:
         result.append((active, y))

   return result
我得到了输出

    [('A', None, None), ('A', 'B', None), ('A', 'B', 'C'), 
(None, None, None), 
('D', None, None), ('D', 'E', None), ('D', 'E', 'F')]

希望它能解决您的问题

什么是变量
以及在“和得到这个”之后显示的数据结构从何而来?我运行了
joinfoo(标签)
如果这是问题的话这个版本的
joinfoo(标签)
返回
[('A',None,None),('A',B',None),('A',B',C'),(None,None),(无,无,无),(无,“E”,无),(无,“E”,“F”)]
。输出看起来不正确。哦,你是对的,但这让我只想重写整个代码,使其能够与多个列表一起工作。问题是空元组与非元组略有不同。这非常接近。在编辑的示例中,它遗漏了
A-E
。我最初的问题没有很好地定义,遗漏了变量输入数据的可扩展性。我现在看到了编辑过的示例。这很有意义。无论如何感谢您的反馈。很高兴您找到了另一个解决方案。这很有效。我做了
labels=map(list,map(None,*labels))
而不是
lines=[…]
然后按照您的代码和您看
做了索引…
。谢谢。