2

I have a List of records of type abc__c. abc__c is a custom object. The record has a field called code__c. What I am trying to accompolish is to group the records in the list based on the code__c.

For example the list might have :

Code__c     abc__c record
30       (Record 1)
40       (Record 2)
40       (Record 3)
50       (Record 4)
30       (Record 5)

I want to group these records based on Code__c in a Map. There could be any number of code__c which is populated dynamically. It is not static. how can I loop through the list and store the records as a list for a particular code__c(Id) in Map?

3 Answers 3

8

You can use a List as a Value for a Map.

Map<Integer, ABC__c[]> codeToABC = new Map<Integer, ABC__c[]>();
for(ABC__c record: abcRecords) {
    if(codeToABC.containsKey(record.Code__c)) {
        // Code already in map
        codeToABC.get(record.Code__c).add(record);
    } else {
        // Code is not yet in Map
        codeToABC.put(record.Code__c, new List<ABC__c> { record });
    }
}

You can swap out Integer for another data type (e.g. if Code is actually a String).

0
5

This is a pretty common pattern. So common it is worthwhile (and pretty straightforward) to write a utility to do so. Here is an example signature:

public class GroupBy
{
    public static Map<String, List<SObject>> strings(List<SObject> records, SObjectField field)
    {
        Map<String, List<SObject>> grouped = new Map<String, List<SObject>>();
        for (SObject record : records)
        {
            String value = (String)record.get(field);
            if (!grouped.containsKey(value))
                grouped.put(value, new List<SObject>());
            grouped.get(value).add(record);
        }
        return grouped;
    }
}

You might want to write signatures for other types, such as Integer, Id, Date, etc. Then any time you need to perform functionality like this, you can just call:

Map<String, List<Abc__c>> codeToAbcs = GroupBy.strings(abcRecords, Abc__c.Code__c);
8
  • 1
    While I love the idea of a utility class like this, your code has several Type-related pitfalls and is more likely to crash/not-compile than you'd hope. There's a couple of arbitrarily pointless, yet required, changes to make this code work the way you'd expect.
    – sfdcfox
    Commented Jan 5, 2017 at 20:42
  • I've been using it for years without issue. You can break it, but in my experience even when I was a newbie you have to kind of go out of your way to do so.
    – Adrian Larson
    Commented Jan 5, 2017 at 20:45
  • 1
    I still +1, just a small note about potential issues. Definitely useful as long as you don't try anything fancy. By the way, you could just change the key to Object so you don't need to worry about data types.
    – sfdcfox
    Commented Jan 5, 2017 at 20:49
  • Now that is a recipe for compile issues and bugs. You can't even do Map<Id, SObject> = new Map<Object, SObject>(). You lose virtually all free type-casting if you make that change. @sfdcfox Besides, I prefer a concrete key type and it's not much more code. As a side benefit, it actually increases your coverage to have a well tested utility like this in case you run into weird issues like when test code sometimes counts against you...
    – Adrian Larson
    Commented Jan 5, 2017 at 20:51
  • Thanks Adrian. This was a good idea to make it as a utility but I would be using it in different places for now. It is just required in one place and I don't see it repeating anywhere else. Appreciate your well though answer though. Thanks
    – SfdcBat
    Commented Jan 5, 2017 at 20:52
0

You can put lists in maps, then list in your map by the group. For example, I put together a quick grouping of accounts by a field here. Just replace the objects and fields to loop through

    List<account> acctList = [Select Name, Client_Executive__c FROM Account LIMIT 100];
set<String> repList = new set<String>();
for (Account acct: acctList) {
    repList.add(acct.Client_Executive__c );
}

Map<string, List<account>> acctMap = new map<string, List<account>>();
for (string rep:repList ) {
    List<Account> repAcctList = new List<Account>();
    for (Account acct: acctList) {
        if (rep == acct.Client_Executive__c) {
            repAcctList.add(acct);
        }
    } 
    acctMap.put(rep, repAcctList);
}
system.debug(acctMap);

You must log in to answer this question.

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