【问题标题】:Building a dictionary from a tab delimited file in a pythonic way以pythonic方式从制表符分隔的文件构建字典
【发布时间】:2013-04-27 11:22:20
【问题描述】:

我编写了以下函数,它接受一个制表符分隔的文件(作为一个字符串)并将其转换为一个字典,其中一个整数作为键,一个包含两个浮点数和值的列表:

def parseResults(self, results):
    """
    Build a dictionary of the SKU (as key), current UK price and current Euro price
    """
    lines = results.split('\n')
    individual_results = []
    for i in range(1,len(lines)-1):
        individual_results.append(lines[i].split('\t'))
    results_dictionary = {}
    for i in range(len(individual_results)):
        results_dictionary[int(individual_results[i][0])] = [float(individual_results[i][1]), float(individual_results[i][2])]
    return results_dictionary

我一直在阅读有关使用列表理解和字典理解的内容,但我真的不知道构建它的最佳方法是什么。

我想我可以使用以下方法简化第一个列表构建:

individual_results = [results.split('\t') for results in lines[1:]]

但我不知道创建字典的最佳方法。我觉得这可能以一种简洁的方式实现,甚至无需创建中间列表。

谢谢,

马特

【问题讨论】:

  • 您能说说results 的样子吗??
  • 嗨,results 看起来类似于:sku\tdelivered-price-gbp\tdelivered-price-euro\tid\n32850238\t15.53\t35.38\t258505\n

标签: python list dictionary python-2.7


【解决方案1】:

像这样:

import csv
import StringIO
results = "sku\tdelivered-price-gbp\tdelivered-price-euro\tid\n32850238\t15.53\t35.38\t258505\n"

data = list(csv.DictReader(StringIO.StringIO(results), delimiter='\t'))
print(data)

输出:

[{'sku': '32850238', 'delivered-price-euro': '35.38', 'delivered-price-gbp': '15.53', 'id': '258505'}]

当然,如果你可以从实际文件中读取,你可以跳过 stringIO 部分。

要构建您想要的字典类型,您可以这样做:

data = {}
for entry in csv.DictReader(StringIO.StringIO(results), delimiter='\t'):
    data[entry['sku']] = [entry['delivered-price-gbp'], entry['delivered-price-euro']]

甚至作为字典理解:

import csv
import StringIO
results = "sku\tdelivered-price-gbp\tdelivered-price-euro\tid\n32850238\t15.53\t35.38\t258505\n10395850\t35.21\t46.32\t3240582\n"

data = {entry['sku']: [entry['delivered-price-gbp'], entry['delivered-price-euro']] 
        for entry in csv.DictReader(StringIO.StringIO(results), delimiter='\t')}
print(data)

但现在阅读起来变得非常困难。

在最后两种情况下,输出将是:

{'32850238': ['15.53', '35.38'], '10395850': ['35.21', '46.32']}

【讨论】:

  • 我能问一下,就性能而言,相对于上面的答案(列表理解,映射之一),它的表现如何?
  • 可能会更好。大部分 csv 模块是用 C 实现的。绝对不会更糟,而且无论如何,性能可能无关紧要。这是一个简单的任务,会在你眨眼之前完成。
  • 对于多行输入,输出会是什么?每个条目对应不同 SKU 的字典列表? (对于数据集sku\tdelivered-price-gbp\tdelivered-price-euro\tid\n32850238\t15.53\t35.38\t258‌​505\n10395850\t35.21\t46.32\t3240582,结果为:data[0] = abovedata[1] = {'sku': '10395850', 'delivered-price-euro': '45.22', 'delivered-price-gbp': '35.21', 'id': '340582'}
  • @Kali_89:好吧,为什么不试试呢? ;-) 是的,这将是一个字典列表。
  • [x for x in something] 就是list(something)
【解决方案2】:

使用标准库中的 CSV 模块,它有一种直接读取字典的方法 csv.DictReader

【讨论】:

    【解决方案3】:

    试试这样的:

    In [8]: from collections import defaultdict
    
    In [9]: with open("filename") as f:
       ...:     dic=defaultdict(list)
       ...:     next(f)                #skip the first line 
       ...:     for line in f:
       ...:         k,v=line.split(None,1)
       ...:         dic[int(k)].extend( map(float,v.split()[:2]) )
       ...:         
    
    In [10]: dic
    Out[10]: defaultdict(<type 'list'>, {32850238: [15.53, 35.38]})
    

    【讨论】:

      【解决方案4】:

      您的代码可以是:

      def parseResults(self, results):  
          lines = results.split('\n')
          li_results = [x.split('\t') for x in lines]
          results_dict = {int(x[0]):map(float,[x[1],x[2]]) for x in li_results[1:]} # skip the header
          return results_dict
      

      或者如果你想要它更短(不推荐):

      def parseResults(self, results):
          return {int(x[0]):map(float,[x[1],x[2]]) for x in [i.split('\t') for i in results.split('\n')][1:]}
      

      输出(来自您给出的字符串):

      {32850238: [15.53, 35.38]}
      

      【讨论】:

      • 像这样的外观 - 我只看到缺少一件事,我不包括标题行吗?要解决此问题,我只需将行 results_dictionary = {int(x[0]):map(float,[x[1]x[2]]) for x in individual_results} 更改为:results_dictionary = {int(x[0]):map(float,[x[1]x[2]]) for x in individual_results[1:]}?
      • 为什么不推荐第二个选项?
      • @Schoolboy:我不明白为什么它会更快。它做同样的事情,只是在一行中。这既不快也不慢。
      猜你喜欢
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多