1

Right now I have an array of "Dragon"s. Each item has two values. An ID and a Count. So my array would look something like this:

Dragon[] dragons = { new Dragon(2, 4), 
                     new Dragon(83, 199), 
                     new Dragon(492, 239), 
                     new Dragon(2, 93), 
                     new Dragon(24, 5) 
                   };

As you can see, I have two Dragons with the ID of 2 in the array. What I would like to accomplish is, when a duplicate is found, just add the count of the duplicate to the count of the first one, and then remove the duplicate Dragon.

I've done this sort of successfully, but I would end up with a null in the middle of the array, and I don't know how to remove the null and then shuffle them.

This is what I have so far but it really doesn't work properly:

public static void dupeCheck(Dragon[] dragons) {
    int end = dragons.length;
    for (int i = 0; i < end; i++) {
        for (int j = i + 1; j < end; j++) {
            if (dragons[i] != null && dragons[j] != null) {
                if (dragons[i].getId() == dragons[j].getId()) {                  
                    dragons[i] = new Item(dragons[i].getId(), dragons[i].getCount() + dragons[j].getCount());
                    dragons[j] = null;
                    end--;
                    j--;
                }
            }
        }
    }
}
David
  • 179
  • 1
  • 1
  • 10
  • 1
    what have you got so far? easy way is to create a list, iterate over your array, check if the id is present, if so add count, otherwise, add object – Stultuske Sep 04 '17 at 07:31
  • 3
    So, this means that a `Dragon` object has both its id and population count? Sounds like a design flaw to me... – fge Sep 04 '17 at 07:32
  • 1
    How about using an ArrayList instead of an array. then you can just `remove()` the dragon – Tschallacka Sep 04 '17 at 07:33
  • @Tschallacka because 'remove' is not what he tries to do – Stultuske Sep 04 '17 at 07:34
  • Are you forced to use an array? If not, look into transferring the data to a Map instead. Seems more fitting to problem. – Henrik Aasted Sørensen Sep 04 '17 at 07:35
  • This is what I have so far: Edit: Formatting was horrible in comments so I will edit my post – David Sep 04 '17 at 07:36
  • @David what you have so far belongs in the question, not a comment – Stultuske Sep 04 '17 at 07:36
  • you can't remove the null, because arrays have a fixed length. either create a new array, or use a List – Stultuske Sep 04 '17 at 07:38
  • How did you end up with duplicate dragons in the first place, can you fix it at the time of insert instead? I would also suggest a map or a set instead. – Viktor Mellgren Sep 04 '17 at 07:40
  • Dragons are randomly generated and I DO want duplicate dragons, but I just want them to merge into one 'slot' so to speak. @ViktorMellgren – David Sep 04 '17 at 07:43
  • Is question that simple or we are asked not to use any APIs or other data structures like List or Maps? If no constraints, please explore ArrayList and iterate and remove the other object after incrementing the count. – Karthik R Sep 04 '17 at 07:51
  • @David, if you have been asked to use only arrays, then having null in middle is not the problem. If you want it ordered, just sort the same array based on the Id of the dragon and thus middle of the array won't be null? – Karthik R Sep 04 '17 at 07:57

3 Answers3

2

You should most probably not maintain the dragon count for each dragon in the dragon class itself.

That aside, even if you are forced to use an array, you should create an intermeditate map to store your dragons.

Map<Integer, Dragon> idToDragon = new HashMap<>();
for (Dragon d : yourArray) {
    // fetch existing dragon with that id or create one if none present
    Dragon t = idToDragon.computeIfAbsent(d.getId(), i -> new Dragon(i, 0));
    // add counts
    t.setCount(t.getCount() + d.getCount());
    // store in map
    idToDragon.put(d.getId(), t);
}

Now the map contains a mapping between the dragons' ids and the dragons, with the correct counts. To create an array out of this map, you can just

Dragon[] newArray = idToDragon.values().toArray(new Dragon[idToDragon.size()]);
daniu
  • 14,137
  • 4
  • 32
  • 53
0

You may be force to store the result in an array but that doesn't mean that you're force to always use an array

One solution could be using the Stream API, group the items adding the count and save the result into an array again. You can get an example of how to use the Stream API to sum values here. Converting a List<T> into a T[] is quite straightforward but anyways, you have an example here

Alberto S.
  • 7,409
  • 6
  • 27
  • 46
0

The size of an array cannot be changed after it's created.

So you need to return either a new array or list containing the merged dragons.

public static Dragon[] merge(Dragon[] dragonArr) {
    return Arrays.stream(dragonArr)
            // 1. obtain a map of dragon IDs and their combined counts
            .collect(groupingBy(Dragon::getId, summingInt(Dragon::getCount)))
            // 2. transform the map entries to dragons
            .entrySet().stream().map(entry -> new Dragon(entry.getKey(), entry.getValue()))
            // 3. collect the result as an array
            .toArray(Dragon[]::new);
}
Luciano van der Veekens
  • 6,307
  • 4
  • 26
  • 30