2010-07-02 81 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