0

Description:

I using a map of maps like this - Map<Id, Map<String, Integer>> boxcolourcount.

Id - boxid

String - Colour

Integer - No:of Balls

I am using this structure to acheive two things

  1. I need to know for every box how many colours of balls are there. this i can achieve without issues

    integer redaballcount = boxcolourcount.get(box.id).get('red');
    
    integer yellowaballcount = boxcolourcount.get(box.id).get('yellow');
    
  2. I need to know total number of balls per box as well

    boxcolourcount.get(box.id) - will return map of colour and balls

    like {'red',20}, {'yellow', 30}

i thought of doing this

for(Id boid : boxcolourcount.keyset())
{
for(string s :boxcolourcount.get(bo.id).keyset()) 
{
   ballcounts+= boxcolourcount.get(box.id).get(s);
}
}

Question:

for use case two - is there a better of doing this? like just adding the values of the Map? like sum(Map.values()) ?

3
  • please edit your post with what you have attempted so far, and indicate where are you stuck? if you need any guidance, please review How to Ask, thanks.
    – glls
    Mar 13, 2018 at 0:58
  • The Apex Map class has a values() method, whose return value you can iterate over...
    – David Reed
    Mar 13, 2018 at 1:00
  • @glls i have updated the OP
    – Mike Y
    Mar 13, 2018 at 1:06

2 Answers 2

1

Here's a self-contained example that you should be able to mimic to get the results you're looking to achieve.

You should consider using Apex Classes to model your object structure and then expose methods to get rolling sums, etc. Using primitive structures for this isn't the easiest approach.

Map<Integer, Map<String, Integer>>  boxcolourcount = new Map<Integer, Map<String, Integer>>();

// put stuff in the box
for (Integer i = 1; i < 10; i++) {

    // build some boxes
    boxcolourcount.put(i, new Map<String, Integer>()); 

    // add some balls to the box
    Map<String, Integer> boxStuff = boxcolourcount.get(i);

    for (String colour : 'red,green,blue'.split(',')) {
        // some number of balls less than 5
        boxStuff.put(colour, Integer.valueOf(Math.random() * 5)); 
    }
}

// sum what's in the box
Integer totalCount = 0;

// count the output
for (Integer boxId : boxcolourcount.keyset()) {
    Map<String, Integer> boxStuff = boxcolourcount.get(boxId);
    system.debug('BoxId:' + boxId + ', ' + JSON.serialize(boxStuff));

    // running total for this specific box
    Integer boxTotal = 0;
    for (String colour : boxStuff.keyset()) {
        Integer colourCount = boxStuff.get(colour);

        // add to the total for this box
        boxTotal += colourCount;

        // add the count to the running total
        totalCount += colourCount;
    }
    system.debug(boxTotal);
}

system.debug(totalCount);

enter image description here

1

No, there isn't a better way to do this, unless whatever code is generating this rather contrived Map could reasonably accumulate a total count along the way (which seems likely).

Apex does not have the type of generic or higher-order functions you might expect from other languages. There's no filter(), map(), reduce() or other functions of that nature. While a few of these are probably possible with the use of interfaces, it's relatively unusual to have a compelling need for that much algorithmic abstraction since the end result isn't a whole lot less verbose (if any) than the naive iterative approach.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .