【问题标题】:Efficiently Searching Nested Lists高效搜索嵌套列表
【发布时间】:2014-01-31 15:48:39
【问题描述】:

我有一个包含税务数据的 csv 文件。我将数据读入嵌套列表,使其格式如下:

['Alabama', 'Single rate', '0.02', '0.04', '5']
['Alabama', 'Single bracket', '500', '3000']
['Alabama', 'Couple rate', '0.02', '0.04', '0.05']
['Alabama', 'Couple bracket', '1000', '6000']

我希望能够输入状态和婚姻状况,然后返回相关的费率和括号列表。我在这里做过,但我觉得有一个更简单的方法。有什么建议吗?

search_state  = 'Alabama'
search_status = 'Single'
rates = []
brackets = []
for sublist in cleaned_data:
  if search_state in sublist[0] and search_status in sublist[1]:
    if 'rate' in sublist[1]:
      rates = [eval(x) for x in sublist[2:]]
    if 'bracket' in sublist[1]:
      brackets = [eval(x) for x in sublist[2:]]

【问题讨论】:

  • 从您的帖子中不清楚cleaned_data 的确切格式。
  • 如果您希望能够使用大量数据多次执行此操作,这正是数据库存在的目的。 stdlib sqlite3 模块非常好。
  • 你基本上永远不会想要使用eval。如果你有一个像'"foo"' 这样的字符串,并且想得到一个像'foo' 这样的字符串,试试s[1:-1],或者,如果你真的,真的坚持,ast.literal_eval(s)
  • sublist 是一个无助于揭示数据格式的名称。您最终可能会通过尝试给出清晰的名称来编写清晰的代码,例如for states, statuses in cleaned_data:。 (我不知道你必须知道导致名称的真正含义的实际格式。)
  • 或者你的原始文件是什么样子的?

标签: python python-3.x


【解决方案1】:

使用嵌套字典会更好:

rates={'Alabama':{'Single rate':['0.02', '0.04', '5'],
                  'Single bracket': ['500', '3000'],
                  'Couple rate': ['0.02', '0.04', '0.05'],
                  'Couple bracket': ['1000', '6000']}}

print(rates['Alabama']['Couple rate'])
# ['0.02', '0.04', '0.05']

假设您的 cdv 文件如下所示:

'Alabama', 'Single rate', '0.02', '0.04', '5'
'Alabama', 'Single bracket', '500', '3000'
'Alabama', 'Couple rate', '0.02', '0.04', '0.05'
'Alabama', 'Couple bracket', '1000', '6000'

你可以这样构造嵌套字典:

import csv

rates={}
with open(ur_file) as f:
    for line in csv.reader(f, skipinitialspace=True, quotechar="'"):
        rates.setdefault(line[0],{})[line[1]]=[float(e) for e in line[2:]]

print(rates)       

打印:

{'Alabama': {'Couple rate': [0.02, 0.04, 0.05], 
 'Single rate': [0.02, 0.04, 5.0], 
 'Single bracket': [500.0, 3000.0], 
 'Couple bracket': [1000.0, 6000.0]}}

编辑

正如 cmets 中所指出的,三层嵌套的 dict 可能更好,比如这个数据结构:

rates={'Alabama':{'Single': {'rate':['0.02', '0.04', '5'],
                             'bracket': ['500', '3000']},
                  'Couple': {'rate': ['0.02', '0.04', '0.05'],
                             'bracket': ['1000', '6000']}}}

虽然使用 defaultdict 或 setdefault 来处理缺少键的两层 dict 很简单,但要优雅地处理多个级别需要更多时间。

我最喜欢的是使用像 autovivification 这样的 Perl 子类这样的字典:

class AutoVivify(dict):
    """Implementation of perl's autovivification feature."""
    def __missing__(self, item):
        value = self[item] = type(self)()
        return value 

rates=AutoVivify()
with open(ur_file) as f:
    for line in csv.reader(f, skipinitialspace=True, quotechar="'"):
        state=line[0]
        k1,k2=line[1].split()
        rates[state][k1][k2]=[float(e) for e in line[2:]]

print(rates)  

打印:

{'Alabama': {'Single': { 
                         'rate': [0.02, 0.04, 5.0], 
                         'bracket': [500.0, 3000.0]}, 
             'Couple': {  
                         'rate': [0.02, 0.04, 0.05], 
                         'bracket': [1000.0, 6000.0]}}}

【讨论】:

  • +1,但是拥有三个级别的字典可能会更好,因为“搜索查询”似乎只是“单个”,而预期结果是速率和括号值,即@ 987654329@
  • 当然你说得对——嵌套字典更有意义。
  • @tobias_k,如果可以的话,我也会支持你的答案 - 谢谢!
  • 另外,感谢@mike-graham 提供清理代码的建议。
  • @tobias_k:有点想这样做,但我同意——更好的方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
  • 2016-02-12
  • 2018-10-15
  • 2014-03-06
  • 1970-01-01
相关资源
最近更新 更多