for(AggregateResult hier4: hierarchy)
 {

    fld4.add((String)hier4.get(Field1));
    fld5.add((String)hier4.get(Field2));
    fld6.add((String)hier4.get(Field3));

    string Soqlstr3=' Select Name ' +' FROM ' + val + ' WHERE ' + Field1 + ' = : fld4  ' + ' AND ' +
           Field2 + ' = : fld5 ' + ' AND ' +
            Field3 + ' = : fld6 ';

    hierarchy2 = database.Query(Soqlstr3);

   }

I have a list named hierarchy2 which gives the following values in it dynamically:

{prudhvi,prudhvi,prudhvi,sampills,sampills};

now I want to divide this list into two sublists like this -

Sublist1-{prudhvi,prudhvi,prudhvi} 


sublist2-{sampills,sampills}.

The list values might change since the query is dynamic. one time it may come like -

{prudhvi,prudhvi,prudhvi,sampills,sampills};

& other time it may come like:

{prudhvi,prudhvi,prudhvi,sampills,sampills,tej,tej,tej};

so in this case I should get 3 sublists

  1. {prudhvi,prudhvi,prudhvi} ,
  2. {sampills,sampills} ,
  3. {prudhvi,prudhvi,prudhvi}

Please suggest me the logic.

Note: hierarchy is a resultant list of a dynamic query. so the number of duplicates may increase or decrease . so depending on the duplicate groups , I need hierarchy to get into number of subsets basing on the duplicates which I get. I need sublists for the purpose of further querying.

  • You need duplicate records in sublists? – Pranay Jaiswal Dec 6 at 10:41
  • Likely . I want to divide my main list into sublists with same names as I have mentioned in my example . – kristy Dec 6 at 10:44
  • Can there be more than 2 unique values in the parent list? – Pranay Jaiswal Dec 6 at 10:47
  • Yes .... the above mentioned list a sample example. the list result might even come in this manner - > {prudhvi,prudhvi,prudhvi,sampills,sampills,tej,tej,tej,tej}; In such case - I need this list to get divided into 3 sublists . Like -Sub List 1:{prudhvi,prudhvi,prudhvi} , Sub List2:{sampills,sampills} , Sub List3:{tej,tej,tej}. – kristy Dec 6 at 10:51
  • 3
    I think this is an x-y problem. I strongly suspect there is a better solution using either a Set, a Map, or refactoring your original query to use an aggregate. Can you share more detail about your use case? – David Reed Dec 6 at 11:56
up vote 0 down vote accepted

I think that you can do something similar to this....

// Lest say you a have a list like this one
List<String> stringList = new List<String>{'prudhvi', 'prudhvi', 'prudhvi', 'sampills', 'sampills'}; 

   // These lists will contain the different values 
   List<String> a = new List<String>(); 
   List<String> b = new List<String>();

 for(String st : stringList)
 {
     if(st == 'prudhvi'){
         a.add(st); 
     }else{
         b.add(st); 
     }
 }
system.debug('This is list a: ' +a); 
system.debug('This is list a: ' +b); 

For this you need to know the values within the initial list. You can find a way to organize these values but it is, as David Reed mentioned, better to go for a map or set. This is not, by any means, a total solution but it could help you to get what you want. If you want to have only one value and use some kind of filter to remove duplicate strings, send all values to a Set.

This is with the Set of strings.... just past the list to the Set collection and you will get only one value, no duplicates.

 // Lest say you a have a list like this one
List<String> stringList = new List<String>{'prudhvi', 'prudhvi', 'prudhvi', 'sampills', 'sampills'}; 

   // These lists will contain the different values 
   List<String> a = new List<String>(); 
   List<String> b = new List<String>();
   Set<String>  c = new Set<String>(stringList);

 for(String st : stringList)
 {
     if(st == 'prudhvi'){
         a.add(st); 
     }else{
         b.add(st); 
     }
 }
system.debug('This is list a: ' +a); 
system.debug('This is list b: ' +b); 
system.debug('This is set c: ' +c);

Output:

enter image description here

I don't fully understand your requirements but you could use the list.size() to get a number of strings in a List<String> and execute certain logic structure based on that. For that you most definitely need to move to maps.

  • for(AggregateResult hier4:hierarchy){ fld4.add((String)hier4.get(Field1)); fld5.add((String)hier4.get(Field2)); fld6.add((String)hier4.get(Field3)); string Soqlstr3=' Select Name ' +' FROM ' + val + ' WHERE ' + Field1 + ' = : fld4 ' + ' AND ' + Field2 + ' = : fld5 ' + ' AND ' + Field3 + ' = : fld6 '; hierarchy2 = database.Query(Soqlstr3); } – kristy Dec 6 at 12:45
  • Why don't you update your question with that code better than adding a comment here? – Carlos Naranjo Dec 6 at 12:49
  • done sir. Please do see the edited question and help me please – kristy Dec 6 at 12:55
  • Do you know the total or maximum number of sublist that you need to generate from your query? ... Other thing to be aware of, queries inside loops it is probably not a good idea. – Carlos Naranjo Dec 6 at 13:12
  • Yes I do know about it . But I'm doing this as a testing phase to understand the logic . Coming to your question there might be around 1000 subists. For now as testing .... let us take like 10 sublists – kristy Dec 6 at 13:19

When you are looking to store an unknown quantity of items, a collection (List, Set, or Map) is the right tool for the job.

Apex (and many other languages) allows us to make nested collections. So, when the thing you need to store is an unknown quantity of collections, then you need something like a List<List<String>>.

For your particular case, I think a Map<String, List<String>> would be the most appropriate.

Why not a List<List<String>>?

If you were to use a List<List<String>>, to add a new element you would need to iterate over every sublist until you found one that already has an element that matches your current element (and add a new list if you don't find any such sublist).

That, to me, sounds inefficient (I get the feeling that inserting/searching would be of class O(n^2) time complexity) and inelegant.

Why a Map<String, List<String>>?

On the other hand, a Map<String, List<String>> allows you to effectively "label" the sublists. That makes it very easy (and very fast) to determine if you already have a sublist for [your current string here], to create a new sublist if you don't, or to add to an existing sublist.

A brief code example

Map<String, List<String>> mapOfLists = new Map<String, List<String>>();
for(String currentString :myStringList){
    if(!mapOfLists.containsKey(currentString)){
        //put a new List<String> into the map for current string
        mapOfLists.put(currentString, new List<String>());
    }

    // we are guaranteed to have at least an empty list in the map for the current string
    //   at this point.
    // Generally speaking, non-primitive types (i.e. things that aren't Integer, Boolean
    //   String, etc...) are stored and retrieved by reference.
    // That means that if we get() our list from the map, and add() a new value to that list,
    //   the list in the map itself will also be updated.
    // This means that we don't need to do something like map.put(key, map.get(key).operation())
    mapOfLists.get(currentString).add(currentString);
}

This approach, the collection of collections, automatically handles any number of sublists regardless if you're expecting 2 sublists or 20,000 sublists (though at that many sublists, you're probably going to start to run into governor limits such as the total number of queried rows per transaction).

A Parting Note

As mentioned in the comments, this does seem like an X-Y problem.

Requiring duplicate strings is a red flag to me. I'd investigate the code that uses these sublists to see if you could get away with simply knowing what the unique strings are (and maybe also how many times each string appeared in the list).

You may also be able to use an aggregate query to gather this information, and remove the need for any of this extra code altogether.

I believe you'll learn more, and get better answers, if in the future you describe the overall problem that you're trying to solve in addition to the approach you're currently taking.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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