【问题标题】:Iterate over python dictionary to retrieve only required rows迭代 python 字典以仅检索所需的行
【发布时间】:2017-04-03 00:39:36
【问题描述】:

我正在从外部来源获取 HTML 表格格式的数据 -

from xml.etree import ElementTree as ET

s = """<table>
  <tr><th>Release</th><th>REFDB</th><th>URL</th></tr>
  <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr>
  <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr>
</table>
"""

用于将html表格转换为字典

table = ET.XML(s)
rows = iter(table)
headers = [col.text for col in next(rows)]
for row in rows:
    values = [col.text for col in row]
    out = dict(zip(headers, values))

现在我的预期输出如下,因为我将从命令行参数传递发布版本。 $ python myscript.py 3.7.3(我有一个代码) 我正在寻找一种解决方案,以便在找到特定的发布版本时遍历字典 - 在我的情况下,它是 3.7.3

Release Version - 3.7.3
REFDB - 12345
URL - http://google.com

【问题讨论】:

  • out 只包含最后一个

标签: python list dictionary arraylist ordereddictionary


【解决方案1】:

假设每个版本只有一行,并且您根本不需要其他版本,您可以创建一个解析 HTML 并在找到代表版本时立即返回 dict 的函数。如果没有找到版本,它可能会返回None

from xml.etree import ElementTree as ET

s = """<table>
  <tr><th>Release</th><th>REFDB</th><th>URL</th></tr>
  <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr>
  <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr>
</table>
"""

def find_version(ver):
    table = ET.XML(s)
    rows = iter(table)
    headers = [col.text for col in next(rows)]
    for row in rows:
        values = [col.text for col in row]
        out = dict(zip(headers, values))
        if out['Release'] == ver:
            return out

    return None

res = find_version('3.7.3')
if res:
    for x in res.items():
        print(' - '.join(x))
else:
    print 'Version not found'

输出:

Release - 3.7.3
URL - http://google.com
REFDB - 12345

【讨论】:

    【解决方案2】:

    你不需要字典。只需解析每一行的内容,看看发布版本是否与您的输入匹配:

    #coding:utf-8
    
    import sys
    from lxml import html
    
    if len(sys.argv) != 2:
        raise Exception("Please provide release version only")
    
    release_input = sys.argv[1].strip()
    
    data = """<table>
      <tr><th>Release</th><th>REFDB</th><th>URL</th></tr>
      <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr>
      <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr>
    </table>
    """
    
    tree = html.fromstring(data)
    for row in tree.xpath('//tr')[1:]:
        release, refbd, url = row.xpath('.//td/text()')
        if release_input == release:
            print("Release Version - {}".format(release))
            print("REFBD - {}".format(refbd))
            print("URL - {}".format(url))
            break
    
    print("{} release version wasn't found".format(release_input))
    

    【讨论】:

    • 谢谢安德烈斯,我正是在找这个。
    • @vpd 很高兴我的回答有所帮助。如果它帮助您解决问题,请不要忘记接受我的回答(作为您问题的答案):)
    【解决方案3】:
    from xml.etree import ElementTree as ET
    
    s = """<table>
      <tr><th>Release</th><th>REFDB</th><th>URL</th></tr>
      <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr>
      <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr>
    </table>
    """
    
    table = ET.XML(s)
    rows = iter(table)
    headers = [col.text for col in next(rows)]
    master = {}
    
    for row in rows:
        values = [col.text for col in row]
        out = dict(zip(headers, values))
        if 'Release' in out:
            master[out['Release']] = out
    
    # Use the release to get the right dict out of master
    print(master)
    if in_data in master:
        for k, v in master[in_data]:
            # print here
            pass
    else:
        print('Error')
    

    【讨论】:

      【解决方案4】:
      import lxml.html
      from collections import namedtuple
      s = """<table>
        <tr><th>Release</th><th>REFDB</th><th>URL</th></tr>
        <tr><td>3.7.3</td><td>12345</td><td>http://google.com</td></tr>
        <tr><td>3.7.4</td><td>456789</td><td>http://foo.com</td></tr>
        <tr><td>3.7.5</td><td>151515</td><td>http://foo.com</td></tr>
      </table>
      """
      def info_gen(rows):
      
          info = namedtuple('info', ['Release', 'REFDB', 'URL'])
          for row in rows:
              yield info(*row.xpath('.//text()'))
      
      html = lxml.html.fromstring(s)
      rows = html.xpath('//table//tr[td]')
      
      Release = input("Enter Release:")
      for info in info_gen(rows):
          if Release in info:
              print(info)
              break
      

      出来:

       Enter Release:3.7.5
      info(Release='3.7.5', REFDB='151515', URL='http://foo.com')
      

      【讨论】:

        【解决方案5】:

        如果您将字典累积在一个列表中:

        result = []
        for row in rows:
            values = [col.text for col in row]
            result.append(dict(zip(headers, values)))
        

        您可以过滤列表 -

        import operator
        value = '3.7.3'
        release = operator.itemgetter('Release')
        refdb = operator.itemgetter('REFDB')
        url = operator.itemgetter('URL')
        data = [d for d in result if release(d) == value]
        

        然后打印所有通过过滤器的字典 -

        f_string = 'Release Version - {}\nREFDB - {}\nURL - {}'
        for d in data:
            print(f_string.format(release(d), refdb(d), url(d)))
        

        【讨论】:

          猜你喜欢
          • 2013-07-21
          • 1970-01-01
          • 2013-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-29
          相关资源
          最近更新 更多