2011-08-25 117 views
1

我看到一個earlier post它試圖在Python中做類似的事情。結合列表中的類似項目

這是一個我想要的東西的例子。讓我們說我有List。

public class MyObject { 
    private String purchase; 
    private Double price; 
} 

讓我們說,一個典型的List<MyObject>將舉行:

Bike 95.00 
Clothes 24.99 
Clothes 10.76 
Food 6.35 
Food 91.46 

我希望所有購買相同價值的物品組合成與總結該項目的價格單個項目。例如,衣服將是價格爲35.75的單件商品(如果我已經正確添加了該商品)。

我想過做它的方式是:

  1. Collections.sort名單通過購買用於爲O(n log n)的
  2. 走排序列表(這是一個ArrayList我使用)作爲同一項目將是連續的並且一次對兩個項目執行合併O(n)

給出O(n log n)的總運行時間。

現在對我來說這聽起來很合理,但是有沒有一個圖書館在那裏至少擊敗了我常量的褲子?如果存在的話,我總是支持使用簡化版本。那麼是否有任何現有的實現可以考慮使用或改進我的算法?

編輯

想着我歸結情況下,我昨天回家後,是的,我很容易看到它是一個地圖。我所要做的就是將其減少到我發佈的更簡單的問題,並且變得非常明顯。我真正的結構是

public class MyObject { 
    Map bucketOfStuff; 
} 

在現實中,bucketOfStuff真是Map<String, Object>這裏有時的值是一個字符串,有時值是雙(它也可以是有時一個整數,但嘿,我可以把它當作雙) 。對於所有類型爲String的對象,它們將用於形成此問題的關鍵。所以,如果我有

  • 顏色=>紅
  • 大小=>小
  • 紋理=>平滑

然後,我可以編碼所有成一個字符串,如Red,Small,Smooth,因爲我知道逗號將不會是任何值中存在的字符,因此我可以將其用作分隔符。

對於我們假設的新地圖的值,它會是List,因爲我必須對所有bucketOfStuff值(雙倍)執行(數學)矢量加法。因此,如果我使用上面的分隔符,擬議的新映射將是Map<List<String>, List<Double>>或簡單地Map<String, List<Double>>

另一件破壞了我的思維過程的事情是,最後集合必須是一個List來傳遞,所以我以一種狹隘的思維方式思考一路列表。所以我必須能夠重建有點涉及的原始對象,但並非不可能。感謝所有的幫助和良好的接觸。

編輯

我要修改我的描述略有因爲我記得,我應該保持List<MyObject>的原始排序,因此,我原來的解決辦法是不正確反正因爲我是做了排序。因此,我將繼續遵循所提供的協助路徑並使用LinkedHashMap<String, List<Double>>。來自​​「此鏈接列表定義了迭代排序,通常是鍵插入到映射中的順序(插入順序)」。

+0

我想你大概可以將它們存儲在一個'HashMap',然後通過陣列走,並且插入到地圖,或更新的價格作爲必要。單步走 - O(n)。 HashMap中的單一訪問是O(1)(...我認爲?),N次(So,O(n)?)。像我想的東西....然後,只需調用'指定者()'如果有必要。 –

回答

5

您鏈接的問題似乎是在模糊匹配更感興趣(兩個字符串被「足夠接近」)彼此,但是從你的問題,好像你在組合是相同的術語只是感興趣。

如果是這種情況,您可以使用標準HashMap在O(n)時間內完成此操作。特別是,你的算法可以工作是這樣的:

  1. String構建一個HashMapDouble
  2. 對於列表中的每個元素:
    1. 如果命名對象不在HashMap生存,以價值等於價格將其插入。
    2. 如果命名對象確實存在於HashMap中,請通過添加與當前對象關聯的值來更新該值。
  3. 遍歷HashMap和每個元素,從鍵/值對創建一個新的MyObject

步驟1需要O(1)次。第2步需要O(n)時間,因爲你只對每個元素進行持續工作。最後,第3步再次花費O(n)時間,因爲您必須僅訪問一次HashMap中的每個元素。總的來說,這是O(n),它比O(n log n)基於排序的解決方案漸近地快。我也覺得這是非常容易的代碼了,因爲你不需要定義你的類型Comparator,可以只使用標準的,現成的Java組件。

希望這會有所幫助!

+0

25秒更快,並有更好的解釋:) +1 – Paulpro

0

,您可以輕鬆創建地圖的形式StringDouble(或double),並通過列表中添加到雙行走做到在O(N)如果purchase已經是一個關鍵,或插入,如果一個新條目它不是。

0

懇求嘗試用這種方式來做到這一點

public static ArrayList<EntryData> CompineEntries(EntryData... Entries) { 
    ArrayList<EntryData> Compined = new ArrayList(); 
    for (int i = 0; i < Entries.length; i++) { 
     boolean found = false; 
     for (int j = 0; j < Compined.size(); j++) { 
      if (Entries[i].SubAccountID == Compined.get(j).SubAccountID) { 
       Compined.get(j).Value += Entries[i].Value; 
       found = true; 
      } 
     } 
     if (!found) { 
      Compined.add(Entries[i]); 
     } 
    } 
    return Compined; 
}