2010-07-02 63 views
2

我解析了一个没有分隔符的字符串,但是在字段开始和结束时都有特定的索引。这里是我的列表理解,从字符串生成一个列表:写更好的方法列表理解?

field_breaks = [(0,2), (2,10), (10,13), (13, 21), (21, 32), (32, 43), (43, 51), (51, 54), (54, 55), (55, 57), (57, 61), (61, 63), (63, 113), (113, 163), (163, 213), (213, 238), (238, 240), (240, 250), (250, 300)] 
s = '4100100297LICACTIVE 09-JUN-198131-DEC-2010P0   Y12490227WYVERN RESTAURANTS INC       1351 HEALDSBURG AVE                     HEALDSBURG    CA95448  ROUND TABLE PIZZA         575 W COLLEGE AVE         STE 201           SANTA ROSA    CA95401    ' 
data = [s[x[0]:x[1]].strip() for x in field_breaks] 

任何关于如何改善这个问题的建议?

+0

这让我想起了这个固定宽度的格式:http://thedailywtf.com/articles/wellformed-xml.aspx – icktoofay 2010-07-02 05:23:49

+0

@ icktoofay-哈,是的。不幸的是,这个数据没有真正的API ... – 2010-07-02 05:32:20

+0

我假设真正的代码从文件中读取数据,而不是将其存储在字符串文字中。至少,我希望如此。 – dan04 2010-07-02 06:22:34

回答

7

您可以通过执行削减一半的field_breaks列表:

field_breaks = [0, 2, 10, 13, 21, 32, 43, ..., 250, 300] 
s = ... 
data = [s[x[0]:x[1]].strip() for x in zip(field_breaks[:-1], field_breaks[1:])] 
+0

+1:减少冗余和文书错误风险的好主意。将此与Tomasz Wysocki的解决方案结合起来,它非常完美。易于阅读。 – 2010-07-02 06:14:55

+0

谢谢!我打算跟这个一起去,因为我喜欢减少field_breaks的想法。 – 2010-07-02 15:08:41

7

您可以使用元组拆包清晰的代码:使用方式

data = [s[a:b].strip() for a,b in field_breaks] 
+2

+1,这也可以和dan04的想法结合使用(可能使用['itertools'文档](http://docs.python.org/library/itertools.html)中的'pairwise') – 2010-07-02 06:04:07

0

这里map

data = map(s.__getslice__, *zip(*field_breaks)) 
3

说实话,我没有发现按列解析的方法非常可读,而且我质疑其可维护性(关闭一个错误等)。虽然我确信列表理解在这种情况下非常有效,并且建议的基于zip的解决方案对它有很好的功能调整。

相反,我打算从左边的字段中扔掉垒球,因为列表解析部分是为了让您的代码更具说明性。完全不同的东西,请考虑以下方法基于pyparsing模块:

def Fixed(chars, width): 
    return Word(chars, exact=width) 

myDate = Combine(Fixed(nums,2) + Literal('-') + Fixed(alphas,3) + Literal('-') 
       + Fixed(nums,4)) 

fullRow = Fixed(nums,2) + Fixed(nums,8) + Fixed(alphas,3) + Fixed(alphas,8) 
      + myDate + myDate + ... 

data = fullRow.parseString(s) 
# should be ['41', '00100297', 'LIC', 'ACTIVE ', 
#   '09-JUN-1981', '31-DEC-2010', ...] 

为了使这更声明,你可以为你遇到它们命名每个字段。我不知道这些字段实际上是什么,但类似:

someId = Fixed(nums,2) 
someOtherId = Fixed(nums,8) 
recordType = Fixed(alphas,3) 
recordStatus = Fixed(alphas,8) 
birthDate = myDate 
issueDate = myDate 
fullRow = someId + someOtherId + recordType + recordStatus 
      + birthDate + issueDate + ... 

现在,像这样的方法可能不会破坏任何陆地速度记录。但是,圣牛,你不觉得这更容易阅读和维护?

+0

非常好 - 我将添加的所有内容都是在解析过程中将mydate转换为Python数据时间的分析操作,以及一些结果名称,以便值解析后可轻松访问,并且日期已可用作日期时间。 (固定也是一个不错的小帮手。) – PaulMcG 2010-07-10 06:57:10