2011-06-15 64 views
6

我有數據,看起來像:如何使用Python的csv模塊拆分雙管道分隔數據

"1234"||"abcd"||"a1s1" 

我試圖讀取和使用Python的CSV讀者和作家寫的。 由於csv模塊的分隔符僅限於單個字符,有沒有什麼辦法可以乾淨地檢索數據?我不能刪除空列,因爲它是一個龐大的數據集,需要以時間限制的方式進行處理。任何想法都會有所幫助。

+1

你說你不能就讓它去,然後取出後的空列可選的報價。當你嘗試時,它是什麼因素太慢? – 2011-06-15 02:48:09

+0

問題應該指出我們是否可以從示例數據中推廣。我的答案在下面假設'是'。 – 2012-07-01 00:30:06

回答

12

The docs和實驗證明,只有單字符分隔符是允許的。

由於cvs.reader接受支持迭代器協議的任何對象,則可以使用發電機的語法與| -s取代|| -s,再喂該發電機向讀者:

def read_this_funky_csv(source): 
    # be sure to pass a source object that supports 
    # iteration (e.g. a file object, or a list of csv text lines) 
    return csv.reader((line.replace('||', '|') for line in source), delimiter='|') 

此代碼是非常有效的因爲它在時間上的一個CSV線運行,提供您的CSV源線的產量不超過可用的RAM :)

+7

推測使用雙管分隔符的原因是因爲在給定值中可能存在單個管道。 – Arafangion 2011-06-15 04:03:36

+0

@Arafangion:是的。也許需要更復雜的生成器表達式來緩解這個缺陷。 – 2011-06-15 04:38:09

+0

@Arafangion只需用另一個分隔符(,; $%} ^ø或其他)在一個值中不會出現的雙管分隔符替換即可。 – 2012-08-17 08:43:03

1

不幸的是,分隔符是由下一個字符來表示這意味着它是不可能有它除Py之外的其他任何字符馬拉松。好消息是,它是可以忽略它們是空值:

reader = csv.reader(['"1234"||"abcd"||"a1s1"'], delimiter='|') 
#iterate through the reader. 
for x in reader: 
    #you have to use a numeric range here to ensure that you eliminate the 
    #right things. 
    for i in range(len(x)): 
     #Odd indexes will be discarded. 
     if i%2 == 0: x[i] #x[i] where i%2 == 0 represents the values you want. 

還有其他的方法來完成這個(函數可以寫爲一個),但是這給你所需要的邏輯。

+0

你將如何處理:'1234 || ab | cd || a1s1'? – Arafangion 2011-06-15 04:53:51

+0

@Arafangion最初的例子不僅僅是管道劃定的,它是管道和雙引號劃定的。這意味着csv.reader將忽略行中心的管道。 – cwallenpoole 2011-06-15 05:06:53

2
>>> import csv 
>>> reader = csv.reader(['"1234"||"abcd"||"a1s1"'], delimiter='|') 
>>> for row in reader: 
...  assert not ''.join(row[1::2]) 
...  row = row[0::2] 
...  print row 
... 
['1234', 'abcd', 'a1s1'] 
>>> 
1

如果你的數據從字面上看起來像例子(字段不會包含「||」,總是引用),你能容忍引號,還是願意以後切片他們,只是使用.split如果分隔符領域內發現只需要

>>> '"1234"||"abcd"||"a1s1"'.split('||') 
['"1234"', '"abcd"', '"a1s1"'] 
>>> list(s[1:-1] for s in '"1234"||"abcd"||"a1s1"'.split('||')) 
['1234', 'abcd', 'a1s1'] 

CSV或刪除周圍領域