【问题标题】:Python: If dict keys in linePython:如果字典键在行
【发布时间】:2012-12-13 19:51:23
【问题描述】:

找到了这个关于如何检查字符串列表是否在一行内的好答案 How to check if a line has one of the strings in a list?

但是尝试用字典中的键做类似的事情似乎对我来说不起作用:

import urllib2

url_info = urllib2.urlopen('http://rss.timegenie.com/forex.xml')
currencies = {"DKK": [], "SEK": []}
print currencies.keys()
testCounter = 0

for line in url_info:
    if any(countryCode in line for countryCode in currencies.keys()):
        testCounter += 1
    if "DKK" in line or "SEK" in line:
        print line
print "testCounter is %i and should be 2 - if not debug the code" % (testCounter)

输出:

['SEK', 'DKK']
<code>DKK</code>
<code>SEK</code>
testCounter is 377 and should be 2 - if not debug the code

认为也许我的问题是因为 .keys() 给了我一个数组而不是一个列表。但还没有弄清楚如何转换它。 .

【问题讨论】:

  • 我刚刚运行了这个,testCounter 是 2,而不是 377。如果遇到意外匹配,我建议在计算匹配时打印出当前行。
  • countryCode in currencies 在功能上等同于countryCode in currencies.keys()

标签: python rss python-2.7


【解决方案1】:

改变:

any(countryCode in line for countryCode in currencies.keys())

到:

any([countryCode in line for countryCode in currencies.keys()])

您的原始代码使用生成器表达式,而(我认为)您的意图是列表理解。 见:Generator Expressions vs. List Comprehension

更新: 我发现使用导入了 pylab 的 ipython 解释器得到了与您相同的结果(377 个计数与预期的 2 个计数)。我意识到问题在于“任何”来自 numpy 包,该包旨在处理数组。 接下来,我加载了一个没有 pylab 的 ipython 解释器,这样 'any' 来自 builtin。在这种情况下,您的原始代码有效。 因此,如果您使用 ipython 解释器类型:

help(any)

并确保它来自内置模块。如果是这样,您的原始代码应该可以正常工作。

【讨论】:

  • 这两者之间绝对没有区别,除了第二个使用急切评估来不必要地查找所有匹配项。第一个将在第一个匹配后停止,因为不需要其他匹配即可让 any 返回 true。
  • 好的,你是对的。现在我需要理解为什么第二个给出了预期的结果而第一个没有。谢谢。
  • 我使用的是 IPython ;-) 非常感谢!
【解决方案2】:

这不是检查 xml 文件的好方法。

  1. 速度很慢。您可能会进行 N*M 子字符串搜索,其中 N 是行数,M 是键数。
  2. XML 不是面向行的文本格式。您的子字符串搜索也可以找到属性名称或元素名称,这可能不是您想要的。如果 XML 文件碰巧将其所有元素放在没有空格的一行上(这对于机器生成和处理的 XML 很常见),那么您得到的匹配项将比您预期的要少。

如果你有面向行的文本输入,我建议你从你的键列表中构造一个正则表达式:

import re
linetester = re.compile('|'.join(re.escape(key) for key in currencies))

for match in linetester.finditer(entire_text):
    print match.group(0)

#or if entire_text is too long and you want to consume iteratively:

for line in entire_text:
        for match in linetester.find(line):
            print match.group(0)

然而,既然你有 XML,你应该使用一个真正的 XML 处理器:

import xml.etree.cElementTree as ET

for elem in forex.findall('data/code'):
    if elem.text in currencies:
        print elem.text

如果您只对存在的代码感兴趣而不关心特定条目,则可以使用 set intersection:

codes = frozenset(e.text for e in forex.findall('data/code'))

print codes & frozenset(currencies)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多