【问题标题】:matching between two different structured python lists两个不同的结构化 python 列表之间的匹配
【发布时间】:2016-05-16 11:06:51
【问题描述】:

我使用 python 2.7,我有 2 个列表,一个是这种形状:

t1 = [('go', 'VB'), [('like', 'IN'), [('i', 'PR')]], [('to', 'TO')], [('there', 'RB')]]

另一个是在一个以这种格式存储的文本文件中:

t2 = [go:VB, [like:IN, [i:PR]], [to:TO], [there:RB]]

我想看看 (t1) 是否匹配 (t2)。

我面临的一个问题是文本文件中没有('')的那些,所以它们看起来像变量。

请您帮忙寻找一种匹配这两者的方法。

def match(t1, t2):
    #check here if the nested lists match or not.   
    return True

我尝试将 ( t1 ) 转换为字符串并删除 ' ( ' 和 ' ) ',方法是用空的 '' 替换它们 然后将 ' , ' 替换为 ' : ' 但它给出了很多引号,我认为这不是解决此问题的好主意。

【问题讨论】:

  • 真的是t2 = [go:VB, [like:IN, [i:PR]], [to:TO], [there:RB]] 还是`t2 = "[go:VB, [like:IN, [i:PR]], [to:TO], [there:RB]] "'(列表中带有 "")?
  • 我仍然不清楚你想如何比较。因为理想情况下,我会将列表展平,然后进行比较。另外,你告诉形状,你的意思是第一种类型t1 是Python Shell 解释器中可用的列表吗?
  • t2 以相同形状存储在文本文件中的许多相似文件中:{ [go:VB, [like:IN, [i:PR]], [to:TO], [there: RB]] , .... .... .... }

标签: python list python-2.7 match


【解决方案1】:

这个答案没有使用eval(),这是一个非常不安全的事情。

  1. 使用str 将您的t1 转换为字符串。
  2. replace的帮助下删除t1t1中的所有空格
  3. 使用resub转换t2
  4. 最后,比较字符串
### 1
t1 = str(t1)

### 2
t1 = t1.replace(" ", "")
t2 = t2.replace(" ", "")

### 3
t2 = re.sub(r"(\w+):(\w+)", r"('\1','\2')", t2)

### 4
print(t1 == t2)

编辑

如果你想支持制表符和换行符,你需要这样做

### 2
t1 = "".join(t1.split())
t2 = "".join(t2.split())

【讨论】:

  • 这是使 t2 等于 t1 的一个很好、直接的答案,我真的很喜欢以清晰的步骤简化问题的方式。我的偏好是使 t1 等于 t2,因为(实际上)t2 类似于这个,但一些嵌套列表被替换为变量。
【解决方案2】:

假设您的结构仅由包含两个字符串的列表和元组组成,以下函数应该通过递归生成目标字符串来满足您的需求:

def format_list(l):
  res = "["
  items = []
  for item in l:
    if isinstance(item,list):
      items.append(format_list(item))
    elif isinstance(item,tuple):
      items.append(item[0] + ':' + item[1])
  res += ", ".join(items) + "]"
  return res

【讨论】:

  • 完全正确!!现在可以更容易地将它与其中包含 VARIABLES 的那个进行比较。我应该只放一个 if 语句来检查第二个参数是否是 'VB'、'PN'、'RB' 然后用变量替换它,这将匹配 [A, [like:IN, [B]], [to:TO], [C]]
【解决方案3】:

一种天真的简单的方法 - 使用regex substitution 将字符串从文件转换为 Python 可评估的形式,然后邪恶的eval 它:

import re

s2 = '[go:VB, [like:IN, [i:PR]], [to:TO], [there:RB]]'

# 'go:VB' -> '("go", "VB")'
s2_pyth = re.sub(r'(\w+):(\w+)', r'("\1", "\2")', s2)
# '[("go", "VB"), [("like", "IN"), [("i", "PR")]], [("to", "TO")], [("there", "RB")]]'

l2 = eval(s2_pyth)
# [('go', 'VB'), [('like', 'IN'), [('i', 'PR')]], [('to', 'TO')], [('there', 'RB')]]

if l1 == l2:
    # or whatever more specific comparison

我认为,在这种情况下使用eval(似乎是一项无害的学术 NLP 任务)是可以的。如果您的文本文件中的标记不是严格的字母数字,您可能需要一个更智能的正则表达式 r'\w+' 来匹配它们,也许……。喜欢r'[^\[\]]+'...

【讨论】:

  • 我不需要拆分('='),因为我不会包含 t2 和 t1(只是列表),我会尝试一下
  • 好的,这简化了我的回答:)
  • 哇!从 t2 到 t1 真是太好了!但是反过来呢?实际上,我已经以另一种类似的方式编写了 t2,但我这样呈现它以使其更易于理解。我的 (t2) 已将其第二个参数中具有标签“VB”或“PR”或“RB”的元组替换为 VAIRABLES。所以实际上 t2 是 [A, [like:IN, [B]], [to:TO], [C]]。如果有从 t1 到 t2 的方法,那就更好了。
  • 好吧,如果这些文件具有随机结构,您将进入更复杂的解析领域。如果生成了这些文件,您应该考虑使用一些可用于创建和读取文件的序列化程序,例如 JSON(请参阅json module
  • 非常感谢您的回答。它通过使用正则表达式的力量为我简化了问题。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
相关资源
最近更新 更多