2012-11-29 83 views
2

我有一個長文本文件,有卡車配置。在每一行中,卡車的一些屬性被列爲一個字符串。每個屬性都有字符串中的自己固定寬度的空間,如:使用字典代替Python中的動態變量名稱

2 chracters = number of axles 
2 characters = weight of the first axle 
2 characters = weight of the second axle 
... 
2 characters = weight of the last axle 
2 characters = length of the first axle spacing (spacing means distance between axles) 
2 characters = length of the second axle spacing 
... 
2 characters = length of the last axle spacing 

舉個例子:

031028331004 

是指:

number of axles = 3 
first axle weight = 10 
second axle weight = 28 
third axle weight = 33 
first spacing = 10 
second spacing = 4 

現在,您有一個想法我的文件結構,這裏是我的問題:我想將這些卡車分組在不同的列表中,並根據軸間距命名列表。假設我使用布爾類型的方法,並且如果間距小於6,布爾值爲1,如果它大於6,則布爾值爲0.爲了說明,三軸卡車中的可能結果變爲:

00 #Both spacings > 6 
10 #First spacing < 6, second > 6 
01 #First spacing > 6, second < 6 
11 #Both spacings < 6 

現在,正如你所看到的,3軸卡車沒有太多的結果。但是,如果我有一輛12軸卡車,那麼「可能」組合的數量就會出現問題。事實是,在現實中,你不會看到12軸卡車中軸間距的所有「可能」組合。有一些組合(我不知道哪些組合,但要弄清楚是我的目標),其數量遠遠少於「可能」數量的組合。

我希望代碼創建列表並填充它們以定義我上面提到的屬性的字符串如果只有這樣的組合存在。我想也許我應該創建具有變量名稱的列表,例如:

truck_0300[] 
truck_0301[] 
truck_0310[] 
truck_0311[] 

在飛行中。然而,從我在SF和其他來源讀到的內容,這是非常不鼓勵的。你如何使用字典概念來做到這一點?我知道詞典就像2維數組,有一個鍵(在我的情況下,鍵將是類似於truck_0300,truck_0301等)和值對(再次在我的情況下,值可能是列表,其中包含實際的字符串屬於相應的卡車類型),但我無法弄清楚如何創建該字典,並用變量鍵和值填充它。

任何見識都會受到歡迎! 非常感謝!

+0

你有代碼來解析'031028331004'成有用的東西? – Eric

+0

@Eric我已經做了解析部分。 – marillion

回答

6

你絕對正確地認爲,在範圍內嘗試創建「動態變量」幾乎總是一個壞主意。字典通常是隨着時間的推移建立對象集合的答案,並參照它們...

我沒有完全理解你的應用程序和格式,但是通常來定義和使用你的字典,它看起來像這樣的:

trucks = {} 
trucks['0300'] = ['a'] 
trucks['0300'].append('c') 
trucks['0300'].extend(['c','d']) 

aTruck = trucks['0300'] 

現在,因爲每一個這些應該是你的字符串列表,你可能只是想使用defaultdict,並告訴它使用列表作爲不存在的鍵的默認值:

from collections import defaultdict 

trucks = defaultdict(list) 
trucks['0300'] 
# [] 

請注意,即使它是麩皮d不包含條目的新字典,'truck_0300'鍵仍會返回新列表。這意味着你不必檢查密鑰。只是追加:

trucks = defaultdict(list) 
trucks['0300'].append('a') 

一個defaultdict可能是你想要什麼,因爲你不必在所有預先定義鍵。當你準備好時,它就在那裏。

獲取關鍵的最大值

從您的意見,在這裏是如何得到一個字典的最大值關鍵的例子。這是很容易的,因爲你只需使用max,並確定它應如何確定要使用的密鑰的比較:

d = {'a':10, 'b':5, 'c':50} 
print max(d.iteritems(), key=lambda (k,v): v) 
# ('c', 50) 
d['c'] = 1 
print max(d.iteritems(), key=lambda (k,v): v) 
# ('a', 10) 

所有你需要做的就是定義如何產生一個比較關鍵。在這種情況下,我只是告訴它以價值爲關鍵。對於像這樣簡單的關鍵函數,只需告訴它從對象中提取索引或屬性即可,可以通過使用operator模塊使模塊更加高效,從而使關鍵函數在C中而不是python中作爲lambda:

from operator import itemgetter 
... 
print max(d.iteritems(), key=itemgetter(1)) 
#('c', 50) 

itemgetter創建一個新的可調用將從由環路傳遞的元組拉的第二個項目。

現在假定每個值實際上是一個列表(類似於您的結構)。我們將使它數字的列表,你想找到它擁有最大總列表中的關鍵:

d = {'a': range(1,5), 'b': range(2,4), 'c': range(5,7)} 
print max(d.iteritems(), key=lambda (k,v): sum(v)) 
# ('c', [5, 6]) 
+1

我認爲'卡車'''''''就足夠了;卡車[]'與卡車_前綴具有相同的助記性目的。但除此之外,所有事情都是+1。 – abarnert

+0

@abarnert:的確如此。我剛剛刪除它。謝謝! – jdi

+0

@jdi非常感謝!這幫助我弄清楚詞典是如何工作的。現在我必須弄清楚如何找到對應於字典中最大值的鍵。我認爲字典默認不支持這個。我會檢查是否有方法來翻譯字典。 – marillion

1

如果鍵的數量爲1萬多,那麼這種方法是不可行的。否則,定義一個字典d = {}並對您的行進行循環:

key = line[:4] 
if not key in d.keys(): 
    d[key] = [] 
d[key] += [somevalue] 

我希望這有助於。

+0

鑰匙的最大數量可以是2^11 = 2048,這將是12軸卡車(它有11個間距)。事情是我不想創造所有這些鑰匙,我希望他們創造,如果只有一個匹配的卡車到那種模式。所以,就像在飛行中創建這些關鍵名稱一樣。 – marillion

+0

關於可行性,10k的限制是什麼? – jdi

0

下面是一個完整的解決方案,從字符串輸出:

from collections import namedtuple, defaultdict 

# lightweight class 
Truck = namedtuple('Truck', 'weights spacings') 

def parse_truck(s): 
    # convert to array of numbers 
    numbers = [int(''.join(t)) for t in zip(s[::2], s[1::2])] 

    # check length 
    n = numbers[0] 
    assert n * 2 == len(numbers) 
    numbers = numbers[1:] 

    return Truck(numbers[:n], numbers[n:]) 

trucks = [ 
    parse_truck("031028331004"), 
    ... 
] 

# dictionary where every key contains a list by default 
trucks_by_spacing = defaultdict(list) 

for truck in trucks: 
    # (True, False) instead of '10' 
    key = tuple(space > 6 for space in truck.spacings) 
    trucks_by_spacing[key].append(truck) 

print trucks_by_spacing 

print trucks_by_spacing[True, False]