Reputation: 9708
I saw an earlier post which is trying to do a similar sort of thing in Python.
Here is a boiled down example of what I want. Let us say I have List.
public class MyObject {
private String purchase;
private Double price;
}
Let us say that a typical List<MyObject>
will hold:
Bike 95.00
Clothes 24.99
Clothes 10.76
Food 6.35
Food 91.46
I want all of the items with same purchase value to be combined into a single item with the price summed for that item. For example, clothes would be a single item with price 35.75 (if I have done the addition correctly).
The way I thought about doing it was:
Collections.sort
the list by purchase for O(n log n)ArrayList
I am using) as same items will be consecutive and perform a merge on 2 items at a time O(n)Giving a total runtime of O(n log n).
Now that sounds reasonable to me, however is there a library out there which at the very least beats the pants of my constants? I always support going with a streamlined version if one exists. So are there any existing implementations that I should think about using or improvements over my algorithm?
EDIT
After thinking about my boiled down case as I went home yesterday, yes I easily saw it is a map. All I had to do is reduce it to the simpler problem I posted and it became very obvious. My real structure is
public class MyObject {
Map bucketOfStuff;
}
In reality, bucketOfStuff is really Map<String, Object>
where sometimes the value is a String and sometimes the value is a Double (it can also be an Integer sometimes, but hey I can treat it as double). For all of the objects which are of type String, they would be used to form the key in this problem. So If I had
Then I could encode all into a single String such as Red,Small,Smooth
because I know comma will not be a character present in any of the values so I can use it as a delimiter.
For the value for our hypothetical new Map, it would be List because I have to perform (mathematical) vector addition on all of the bucketOfStuff
values which are doubles. So the proposed new Map would either be Map<List<String>, List<Double>>
or simply Map<String, List<Double>>
if I used the delimiter as above.
Another thing which corrupted my thought process is that in the end the collection has to be a List to pass on so I was in a narrow-minded way thinking List all the way. So I have to be able to reconstruct the original object which is a bit involved, but not impossible. Thanks all for the help and nice catch.
EDIT
I have to modify my description slightly because I just recalled that I should maintain the original ordering of the List<MyObject>
, therefore my original solution would have been incorrect anyway since I was doing the sort. Because of this, I shall continue to follow the path of assistance offered and use a LinkedHashMap<String, List<Double>>
. Coming from Java 6 API "This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order)".
Upvotes: 1
Views: 1335
Reputation: 420
pleas try to do it with this way
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;
}
Upvotes: 0
Reputation: 141877
You can easily do it in O(n) by creating a map form String
to Double
(or double
), and walking through the list adding to the double if the purchase
is already a key, or inserting a new entry if it isn't.
Upvotes: 0
Reputation: 372972
The question you linked seems to be more interested in fuzzy matching (two strings that are "close enough") to one another, but from your question it seems like you're just interested in combining terms that are identical.
If that's the case, you can do this in O(n) time by using a standard HashMap
. In particular, your algorithm could work like this:
HashMap
from String
to Double
.HashMap
, insert it with value equal to the price.HashMap
, update the value by adding in the value associated with the current object.HashMap
and for each element, create a new MyObject
from the key/value pair.Step 1 takes O(1) time. Step 2 takes O(n) time, since you do only constant work for each element. Finally, step 3 takes O(n) time again because you have to visit every element in the HashMap
exactly once. Overall this is O(n), which is asymptotically faster than your O(n log n) sorting-based solution. I also think this is much easier to code up, since you don't need to define a Comparator
for your type and can just use standard, off-the-shelf Java components.
Hope this helps!
Upvotes: 5