0

How to avoid "For loop inside loop" for the below code

For Each Account Conataines multiple Specifications, for the Specifications contains "Region" need to insert the name in Region field on Account

There is No direct relation b/w both objcets, based on the Offer__Id__c on account we are fetching the list of specifications

  Trigger AccountUpdate on Account(Before Insert){
      List<String> Region = new List<String>();
      List<String> SubRegion = new List<String>();
      List<Id>OfferIds= new List<Specification__c>();
      for(Account A :  Trigger.New){
      OfferIds.add(A.Offer__Id__c)
      }
      List<Specification__c> OfferSpec=[Select id ,Name,Level__c,Offer__Id__c from Specification__c where Offer__Id__c IN : OfferIds ]
     // OfferSpec Conatines list List of Specifications
     //For Each Account Conaties multiple Specifications, for the Specifications contains "Region" need to insert the name  in Region field on Account
     ///For Each Account Conaties multiple Specifications, for the Specifications contains "SubRegion" need to insert the name  in SubRegion field on Account
      for(Account Ac: Trigger.New){
          for(Specification__c Off : OfferSpec){

            if(Ac.Offer__Id__c == Offsp.Offer__Id__c && Off.Level__c != null && Off.Level__c.contains('Region')){

                   Region.add(Off.Name);

            }
              else if (Ac.Offer__Id__c == Off.Offer__Id__c && Off.Level__c != null && Off.Level__c.contains('SubRegion')){

                   SubRegion.add(Off.Name);

            }
          }
         string allRegions = string.join(Region,',');
         string allSubRegions = string.join(SubRegion,',');
          Ac.Region__c=allRegions;
          Ac.SubRegion__c=allSubRegions;

      }

    }
2

welcome to the site.

The standard way to do this would be to populate a map of Id to Specification__c, i.e.:

Map<String, Specification__c> specMap = new Map<String, Specification__c>();
List<Specification__c> OfferSpecs =[Select id ,Name,Level__c,Offer__Id__c from Specification__c where Offer__Id__c IN : OfferIds ];

for(Specification__c spec : OfferSpecs) {
    specMap.put(spec.Offer__Id__c, spec);
}

Then when looping through the accounts you don't need the doubly nested loop, you can just do:

specMap.get(Ac.Offer__Id__c);

BUT

I'm guessing from your scenario that there might be many specs for a given Offer__Id__c value... if that's the case you'll need a map of offer ID to a List of specs, and then loop through the matching specs inside of the account loop. I'll leave that as an exercise for you, but the above should get you going. If I'm correct in this assumption you'll still have a doubly nested loop, but it's going to be a lot more focused.

Also consider moving your logic out of the trigger itself so it's re-usable from other classes etc.

  • 1
    I agree with @MattLacey. Further, another benefit of moving the logic out of the trigger itself is that you can properly unit test the code, rather than rely on what is effectively an "integration test" (where you test the code via its usage in the trigger). This also allows unit testing with just in-memory objects (no need for DML operations, as long as you create usable, fake IDs) which means the unit tests also run faster. – Phil W Aug 15 '19 at 7:05

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.