Python

2012-03-25 12 views
11

'da listelerin listesiyle sözlük oluşturma Çok büyük bir dosyam var (yaklaşık 200k girişli). girişler şeklinde şunlardır:Python

A B C D 
B E F 
C A B D 
D 

ben bu dosyayı okuma ve aşağıdaki gibi bir liste halinde saklayarak ediyorum:

text = f.read().split('\n') 

Bu yeni bir satır gördüğünde dosyayı böler.

[[A B C D] [B E F] [C A B D] [D]] 

Ben anahtar değerleri her listeden birinci unsur olduğu artık bir sözlükte bu değerleri saklamak zorunda: aşağıdaki gibi Dolayısıyla metindir. yani anahtarlar A, B, C, D olacaktır. Değerlerin listenin kalan öğeleri olarak girilmesini zor buluyorum. Aşağıdaki yapmış

{A: [B C D]; B: [E F]; C: [A B D]; D: []} 

: gibi yani Sözlük görünmelidir

inlinkDict = {} 
    for doc in text: 
    adoc= doc.split(' ') 
    docid = adoc[0] 
    inlinkDict[docid] = inlinkDict.get(docid,0) + {I do not understand what to put in here} 

benim sözlüğe değerleri eklemelisiniz olarak nasıl yardım edin. Listede, anahtar değer olacak olan herhangi bir öğe yoksa 0 olmalıdır. Örnekte 0.

+0

olmak sözlüğü istiyor musunuz '{A: [B, C, D]; B: [E, F]; C: [A, B, D]; D: []} '? Ya da belki "{A:" B C D "; B: "E F"; C: "A B D"; D: 0} '? – huon

+0

Lütfen yinelenen anahtarlar hakkında ne yapmak istediğinizi söylemek için sorunuzu düzenleyin; foer örneği, "A P Q R" içeren 5. satırınız varsa ne olur? B C D ... değerlerini bir liste olarak nasıl saklamak istiyorsunuz? ['B', 'C', 'D'] '?Boş bir listenin durumunu '0' gibi bir tam sayı değil, boş bir liste olarak göstermek daha iyi olacaktır. –

+0

@JohnMachin: Yinelenen değer yok. Ve evet değerleri bir liste olarak saklamak kesinlikle yardımcı olacaktır. Sorumu düzenleyeceğim. – Nerd

cevap

17

için bir dilim kullanmayı deneyin gibi:

inlinkDict[docid] = adoc[1:] 

Bu size boş bir liste yerine sadece anahtar değeri hattı üzerinde olduğu durum için 0 verecektir.

>>> with open('/tmp/spam.txt') as f: 
... data = [line.strip().split() for line in f.readlines()] 
... 
>>> {d[0]: d[1:] for d in data} 
{'A': ['B', 'C', 'D'], 'C': ['A', 'B', 'D'], 'B': ['E', 'F'], 'D': []} 
>>> {d[0]: ' '.join(d[1:]) if d[1:] else 0 for d in data} 
{'A': 'B C D', 'C': 'A B D', 'B': 'E F', 'D': 0} 

Not: dict anlayışı ile

inlinkDict[docid] = adoc[1:] if adoc[1:] else 0 

kolay yolu: Bir 0 yerine koşullu atama kullanabilirsiniz almak için varsa yani dict tuşları diyelim, benzersiz olmalıdır, 'C' ile başlayan iki satır, birincinin üzerine yazılacaktır.

+0

, bu, 2.7 python'da onli olarak çalışacaktır, daha iyi bir yol dict ([(d [0], d [1:]) için verilerde d)] – pod2metra

+0

Bu, ayrıca tüm dosyayı bellekte okuyacaktır. –

18

bir sözlük anlama bu görevin kısa çalışma yapar:

>>> s = [['A','B','C','D'], ['B','E','F'], ['C','A','B','D'], ['D']] 
>>> {t[0]:t[1:] for t in s} 
{'A': ['B', 'C', 'D'], 'C': ['A', 'B', 'D'], 'B': ['E', 'F'], 'D': []} 
+1

Eski bir python sürümünü dict anlamalarına sahip değilseniz, 'dict (t [0], t [1:] t in s için)' yerine – forivall

+11

kullanabilirsiniz. jeneratör ifadelerini önceleyen python sürümü, '' dict ([(t [0], t [1:]) 'i t) s]) '' için kullanabilirsiniz. Ve bundan daha eski bir versiyon kullanıyorsanız, '' t in s: d [t [0]] = t [1:] '' için kullanabilirsiniz. Ve eğer Python'un bulunmadığı zamana kadar geri döndüyseniz, DartHaster BASIC'i DIM için bir dizi kullanabilirsiniz, böylece bir hash tablosunu kendi karma işlevinizi yazarak simüle edebilirsiniz. Ve, daha yüksek bir dilde olmayan bir sistem üzerinde çalışıyorsanız, assembler kodunuzu makine diline çevirebilir ve programınızı geçiş anahtarları ile girebilirsiniz ... –

+0

Ha, ha, ha. Bu sadece 2.5 ve 2.6 hala çok yaygın ve dict anlayışlar sadece 2.7'de eklendi. – forivall

4

kabul cevap belleğe dosyanın tamamını (eğer büyük bir dosya varsa arzu olmayabilir) okur dışında doğru olduğunu ve Yinelenen anahtarların üzerine yazacaktır.

Python 2.4 edinilebilir defaultdict kullanarak alternatif bir yaklaşım, bu çözer:

from collections import defaultdict 
d = defaultdict(list) 
with open('/tmp/spam.txt') as f: 
    for line in f: 
    parts = line.strip().split() 
    d[parts[0]] += parts[1:] 

Girdi:

 
A B C D 
B E F 
C A B D 
D 
C H I J 

Sonuç:

>>> d = defaultdict(list) 
>>> with open('/tmp/spam.txt') as f: 
... for line in f: 
...  parts = line.strip().split() 
...  d[parts[0]] += parts[1:] 
... 
>>> d['C'] 
['A', 'B', 'D', 'H', 'I', 'J']