2012-08-02 53 views
2

我遇到這個相當頻繁。我有一批數據(存儲在CSV,XML,沒關係)在某些版本的格式:重組數據從平面文件到散列鍵的算法

key1|value1 
key1|value2 
key1|value3 
key2|value4 
key2|value5 
etc. 

,需要能夠處理它以這種形式:

data[key1] => [value1, value2, value3] 
data[key2] => [value4, value5] 
etc. 

從A轉換到B的最佳方法是什麼?我通常像這樣(僞代碼)循環遍歷列表,但我不喜歡我必須重複我的數組構建代碼。

data = [] 
values = [] 
currentKey = "" 
foreach (line in inputData) { 
    key, value = split(line) 
    if ((currentKey != "") and (currentKey != key)) { 
     data[currentKey] = values 
     values = [] 
    } 
    currentKey = key 
    values.add(value) 
} 
// this is the part I don't like, but it's necessary to capture the last group 
data[currentKey] = values 

我特別沒有命名語言,因爲我必須至少在Javascript,C#,Perl和PHP中這樣做。如果有特定語言的解決方案會很棒,但我真的在尋找最高效的通用算法方法。

+3

你的算法使用的值是按鍵分組的事實。實際上,你可以避免這種情況,使代碼更清晰:if(!(key in dictionary))dictionary.add(key,empty);字典[key] .add(value) – Vlad 2012-08-02 17:03:25

+0

我認爲在簡化問題時我丟失了一個重要的部分,這就是我經常需要在將數據放入數據之前收集所有的值[currentKey] - 有時它是一個SQL調用或我正在寫出一個文件。我認爲更大的問題是,我試圖通過結合閱讀和寫作來變得可愛,並且應該循環以解析一次,然後循環解析的數據以創建輸出。 – 2012-08-03 05:56:56

回答

1

您可以更改您的代碼如下:

data = {} 

currentKey = "" 

foreach (line in inputData) { 

    key, value = split(line) 
    if (currentKey != key) { 
     data[key] = [] // like data.put(key,new ArrayList<String>()) in java 
    } 
    data[key].add(value) // like data.get(key).add(value) in java 
    currentKey = key 
} 
+2

可能最好跳過整個'currentkey'業務,並檢查每個行的散列/字典/數組中是否存在密鑰,如果不存在,則爲其添加一個空數組。這避免了整個「鍵必須分組在輸入」問題。 – geoffspear 2012-08-02 17:37:06

+0

你說得對,我就是這麼做的。我以爲他只想解決最後一個問題。 – barak1412 2012-08-02 18:50:56

1

這裏是一個解決方案。首先,創建一個地圖。對於數據文件中的每個條目,找到鍵和值。檢查鑰匙是否在地圖上。如果不是,則將新的列表添加到包含該鍵的新值的映射中。如果鍵已經在地圖中,只需將新值添加到列表中。

def hash = [:] 
new File("test.data").eachLine { String line -> 
    def (key,value) = line.split(/\|/) 
    hash.get(key, []) << value 
} 

println hash 

它打印出如下圖:

[key1:[value1, value2, value3], key2:[value4, value5]] 

無需保持currentKey軌道。

編輯:這是用Groovy編寫的,但在其他語言中應該以相似的方式實現。 hash.get()返回鍵的值或提供的默認值(在上面的代碼片段中是一個空列表),而左移(<<)操作符將某些內容添加到列表中。