1

Need this map to populate the lookup field on a child object, finding id of lookup object by it's Name. e.g. [SELECT Name, Id FROM Account] --> Map<Name, Id>

  • Don't think there is a quickest way, you need to iterate over a for loop to prepare the map. – Raul Aug 27 '19 at 14:17
1

There is no "quick way" to do so; it always requires a loop:

Map<String, Id> name2Id = new Map<String, Id>();
for(Sobject record: records) {
  name2Id.put(record.Name, record.Id);
}

Replace SObject with the correct data type.

|improve this answer|||||
  • Thanks, that's what I've been doing so far (plus query), just thought as this seem to be quite a useful and imho: popular requirement, thought there'd be a clever workaround to avoid these 3 lines. Must be just getting lazy.. – Dextersecret Aug 27 '19 at 14:23
6

Code a loop.

But in general, you will need to build a Map<String, Set<Id>> unless you have duplicate rules that disallow duplicate Account names:

Map<String, Set<Id>> m = new Map<String, Set<Id>>();
for (Account a : [
        select Name, Id 
        from Account
        where ...
        ]) {
    Set<Id> s = m.get(a.Name);
    if (s == null) {
        s = new Set<Id>();
        m.put(a.Name, s);
    }
    s.add(a.Id);
}
|improve this answer|||||
4

To paraphrase Bill Clinton, it depends on the definition of quickest

For me, quickest means quickest to code as unless you have some CPU-sensitive transaction, your time is more valuable than SFDC server time. And this pattern occurs over and over again in your org.

To that end, I built a small library of pivot methods that allow you to do this in one line

Map<String,Account[]> accountsById = 
  Util.pivotSobjectsByString(Account.Name,[SELECT Id, Name FROM Account]);

where the pivot method is defined as:

public static map<String,List<SObject>> pivotSObjectsByString(Schema.SObjectField fldToken, SObject[] sobjList) {
    map<String,List<SObject>>   res = new map<String,List<SObject>> ();
    for (Sobject sobj: sobjList == null ? new list<Sobject>() : sobjlist) {
        String pivotKey = (String) sobj.get(fldToken);
        if (res.containsKey(pivotKey)) {
            res.get(pivotKey).add(sobj);
        }
        else {
            Sobject[] typedSobjs = makeTypedSobjList(sobj); // do this so resulting list.getSobjectType() doesn't return null
            typedSobjs.add(sobj);
            res.put(pivotKey,typedSobjs);
        }
    }
    return res;
}

public static Sobject[] makeTypedSobjList(Sobject sobj) {
    return (Sobject[]) Type.forName('List<'+sobj.getSObjectType()+'>').newInstance();
}

The nice thing about this method (and there are equivalent ones for Decimal, Date, ...) is that you always get back a list of matching sObjects, hence addressing duplicates (or which might be empty) so your calling code merely needs to iterate over lists and never test for null

If you want a more powerful library that allows pivoting on parent fields as well, check out @Aidan library SobjectIndex

|improve this answer|||||
  • Seems like it would be better to name the class Pivot and the method byString. – Adrian Larson Aug 27 '19 at 18:47
  • @AdrianLarson - as usual, you're probably right but I copy-pasted this from my org where I've developed a large library of useful methods into one container. Add this to the pile of good refactoring ideas – cropredy Aug 27 '19 at 18:49
  • Ah, the terrifying monolith. Personally, I would never use anything in a class called Util for fear of being tethered to it. – Adrian Larson Aug 27 '19 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.