2011-06-15 41 views
6

ben var veriyi çift boru ayrılmış veri bölme için piton csv modülü kullanmak: okudum ve Python'un csv okuyucu ve yazar kullanarak yazmaya çalışıyorumnasıl benziyor

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

. csv modülünün sınırlayıcısı tek char ile sınırlı olduğundan, verileri temiz bir şekilde almak için herhangi bir yol var mı? Boş sütunları, zamana bağlı olarak işlenecek devasa büyük bir veri kümesi olduğu için kaldıramayacağım. Herhangi bir düşünce yardımcı olacaktır.

+1

alanları etrafında isteğe bağlı tırnak silin. Denediğinizde hangi faktör çok yavaştı? –

+0

Sorular, örnek verilerden genelleme yapıp yapamayacağımızı belirtmelidir. Benim cevabım 'evet' varsayıyor. –

cevap

12

ve deneyler yalnızca tek karakterli sınırlayıcılara izin verildiğini kanıtlar.

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='|') 

Bu kod oldukça etkilidir: cvs.reader yana

yineleyici protokolünü destekleyen herhangi bir nesne, sen okuyucuya bu jeneratör beslemek sonra | -s ile || -s yerine jeneratör sözdizimi kullanabilirsiniz ve kabul Bir CSV hattında bir seferde çalıştığı için, CSV kaynağınız kullanılabilir RAM'inizi aşmayan satırlar veriyorsa :)

+7

Muhtemelen çift borulu sınırlayıcıların kullanılmasının nedeni, belirli bir değerde tek bir boru olabileceğidir. – Arafangion

+0

@Arafangion: true. Bu kusuru hafifletmek için belki de daha ayrıntılı bir jeneratör ifadesi gerekir. –

+0

@Arafangion Çift borulu sınırlayıcıları, bir değerde oluşmayan başka bir sınırlayıcıyla (,; $%}^ø veya herhangi bir şekilde) değiştirin. –

1

Sınırlayıcı, C cinsinden bir karakterle temsil edilir. Bu, bunun olması imkansız olduğu anlamına gelir. Py'deki tek bir karakterden başka bir şey olmak thon. İyi haber boş olan değerleri göz ardı etmek mümkün olmasıdır:

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. 

var (biri için, yazılmış olabilir bir fonksiyon) Bunu gerçekleştirmek için başka yollar vardır, ama bu size gerekli olan mantığı verir .

+0

Nasıl yapılır: '1234 || ab | cd || a1s1'? – Arafangion

+0

@Arafangion Orijinal örnek sadece boru değil, boru ve çifte alıntıdır. Bu, csv.reader'ın, hattın ortasındaki boruları görmezden geleceği anlamına gelir. – cwallenpoole

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

veri anlamıyla (alanlar '||' içeren ve her zaman cinsindendir asla) ve tırnak işaretleri tolere edebilir veya bunları daha sonra dilimlemekte hazırız örnek gibi görünüyorsa, sadece .split kullanmak

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

csv sınırlayıcı alanları içinde bulunursa sadece ihtiyaç vardır ya sen işin peşini ardından sonra boş sütunları kaldırmak izin göze alamaz söyledi

İlgili konular