function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Bramha1Bramha1 

Sorting a Map by Value

Hi,

 

I would like to know if we can sort a Map by Value. I have a Map like below.

 

Map<Id, Integer> accMap = new Map<Id, Integer>();

 

e.g I have values in the Map like below

 

accMap.put('Id1' , 2);

accMap.put('Id2' , 1);

accMap.put('Id3' , 4);

accMap.put('Id4' , 3);

accMap.put('Id5' , 5);

 

Now i want the Map to be sorted by the Integer value and my output should be like below

 

accMap.put('Id5' , 5);

accMap.put('Id3' , 4);

accMap.put('Id4' , 3);

accMap.put('Id1' , 2);

accMap.put('Id2' , 1);

 

 

Any help will be appriciated.

 

Thanks

 

Bramha

Best Answer chosen by Admin (Salesforce Developers) 
Shashikant SharmaShashikant Sharma

Map do not hae sorting supported, they are a key value pair collection. Now for your issue you need a sorting algo to work and create a list of key according to the order you want. You can use linear search algo or bubble sort from data structure. Please ask if any issue.

All Answers

plusplusbenplusplusben

Maps don't really have a concept of sort order.  If you want to maintain order, I think you'll have to use a List.

Shashikant SharmaShashikant Sharma

Map do not hae sorting supported, they are a key value pair collection. Now for your issue you need a sorting algo to work and create a list of key according to the order you want. You can use linear search algo or bubble sort from data structure. Please ask if any issue.

This was selected as the best answer
Bramha1Bramha1

Hi,

 

Thnaks for the reply guys...Is there any sort of example or brief code which covers this senario. It would be really helpful.

 

 

Thanks

 

Bramha

Ankit AroraAnkit Arora

Sorting on map is not possible. But if you want to sort map with there key then we can do something like this :

 

map<String , Integer> accMap = new Map<String,Integer>() ;
accMap.put('Id2' , 2);
accMap.put('Id1' , 1);
accMap.put('Id4' , 4);
accMap.put('Id3' , 3);
accMap.put('Id5' , 5);

List<String> aList = new List<String>();
aList.addAll(accMap.keySet());
aList.sort();
//so here you will get sorted total base on key
for(String a: aList)
{
   System.debug( '::::::::::::: ' + accMap.get(a)) ;
}

 Please note above code will sort the map on their key and NOT values.

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

Muruganand_SforceMuruganand_Sforce

Ankit

 

 I got this error with your code.

 

Error: Compile Error: expecting a right parentheses, found 'Id2' at line 4 column 11

 

accMap.put('Id2',2);

 

I got this error....

 

Muruganand_Sforce

Ankit AroraAnkit Arora

Would love to see your code as am amazed that the above code is working absolutely perfect for me and not for you.

 

Have you done any changes?? Please post your code here.

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

Muruganand_SforceMuruganand_Sforce

Public class mapsort
{

map<String , Integer> accMap = new Map<String,Integer>();
accMap.put('Id2',2);
accMap.put('Id1',1);
accMap.put('Id4',4);
accMap.put('Id3',3);
accMap.put('Id5',5);

List<String> aList = new List<String>();
aList.addAll(accMap.keySet());
aList.sort();
//so here you will get sorted total base on key
for(String a: aList)
{
   System.debug( '::::::::::::: ' + accMap.get(a)) ;
}

}

Ankit AroraAnkit Arora

You need to do this in constructor or in any method like try this :

 

Public class mapsort
{
	public mapsort()
	{

		map<String , Integer> accMap = new Map<String,Integer>();
		accMap.put('Id2',2);
		accMap.put('Id1',1);
		accMap.put('Id4',4);
		accMap.put('Id3',3);
		accMap.put('Id5',5);

		List<String> aList = new List<String>();
		aList.addAll(accMap.keySet());
		aList.sort();
		//so here you will get sorted total base on key
		for(String a: aList)
		{
		   System.debug( '::::::::::::: ' + accMap.get(a)) ;
		}
	}

}

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

Bramha1Bramha1

Hi Ankit,

 

   Thank you very much. I know we can sort Maps based on the Keys, but i was looking for a solution which could sort the Maps by their Value. 

 

Thanks

 

Bramha

Bramha1Bramha1

Hi Sharma,

 

   Thanks for the idea, i guess we can do it with sorting techniques(bubble sort or linear sort). I was wondering if it would be a efficient way of the dataset is large. I came across a way which would work out.

 

1) reverse the Map into i.e Map<Integer, List<Id>> 

2) And then sort this Map on the key set.

 

 

I guess this would work in my case. Have to check this now. Will get back to you once i am done.

 

 

Thanks

 

Bramha

LakshmanLakshman

Bhrama,

 

Here is the code to get sorted values( in both Ascending and Descending) of a map:

 

Map<String, Integer> accMap = new Map<String,Integer>() ;
accMap.put('ID1' , 20);
accMap.put('ID2' , 10);
accMap.put('ID3' , 40);
accMap.put('ID4' , 30);
accMap.put('ID5' , 50);
List<Integer> value= new List<Integer>(accMap.Values());
value.sort();
System.debug('Sorted values of Map in ascending are:'+value);
List<Integer> descValue = new List<Integer>();
for(Integer i=value.size()-1; i>=0;i--)
{
descValue.add(value.get(i));
}
System.debug('Sorted values of Map in descending are:'+descValue);

 

Regards,

Lakshman

Shashikant SharmaShashikant Sharma

Hi Bramha,

 

I know this way  that I suggested will excute a lot of script statement, but I don't see any other option. I am also waiting to see your code. I will my self will try find a better solution.

 

Bramha1Bramha1

Hi Lakshman,

 

  Thanks for the reply. i guess you didn't get my question correctly. I want the output as a Map rather than a List<Integers>.

 

 

Thanks

 

Bramha

SteveBowerSteveBower

Bramha1, a sorted map makes no sense and you can't have one.

 

You may have the keys of the map sorted by the values, or the values by the keys, or the keys sorted alone, or the values sorted alone, etc.  but you may not have a sorted map.

 

When you say you "want the output as a map" what do you mean?   Do you simply want a the current map of A,B key-value pairs turned into a map of B,A Key value pairs?  You can have that (although duplicates in the values may cause you grief because they will become duplicate keys and you may lose data, etc.).

 

So, would you care to clarify what your goal is?     Is the confusion about the storage in Apex of the data that you want to create, or is there some output format you're striving for?

 

Inquiring minds!  Best, Steve.

LakshmanLakshman

I know your requirement buddy. This is just a work around to get values of a Map sorted in form of List as there is no API available to sort the Map in Apex.

One more thing you can do is put the values in Map in ordered way. :)

Let me know if you are done with building your algorithm.

 

-Lakshman

SteveBowerSteveBower

You can't add values into a Map in an ordered way.   It doesn't not matter what order you enter them, once they are in the map they are unordered by definition.  A map has no intrinsic order.

 

 

And, if you just want the values of the Map in a sorted List, you can just say

 

Map<String, Integer> x = ... whatever

 

List<Integer> sortedValues = x.values().sort().

 

Best, Steve.

Shashikant SharmaShashikant Sharma

Hi Bramha,

 

I sorted a MAP I think so , please verify it

 

Map<String, Integer> accMap = new Map<String,Integer>() ;
accMap.put('ID1' , 20);
accMap.put('ID2' , 10);
accMap.put('ID3' , 40);
accMap.put('ID4' , 30);
accMap.put('ID5' , 50);

MAP<Integer , List<String>>  reverseMap =  new MAP<Integer , List<String>>();

List<String> tempL = new List<String>();
for(String k : accMap.KeySet())
          {
                 if(reverseMap.containsKey(accMap.get(k)))      
                { 
                        
                       tempL =reverseMap.get(accMap.get(k));
               }  
               else
                 tempL = new List<String>();
          
              tempL.add(k);
              reverseMap.put(accMap.get(k) , tempL);
           }




List<String> aList = new List<String>();
aList.addAll(accMap.keySet());
List<Integer> value= new List<Integer>();
Set<String> key = new Set<String>();
for(String s : aList)
{
value.add(accMap.get(s));
}
value.sort();

List<Integer> descValue = new List<Integer>();
for(Integer i=value.size()-1; i>=0;i--)
{
descValue.add(value.get(i));
}

List<String> sortedKey = new List<String>();
for(Integer d : descValue)
{
         sortedKey.addAll(reverseMap.get(d));  
}

//I have debug values coming out of map are in reverse sorted error
system.debug('*************** Sorted KEy : '+ sortedKey);
for(String finalK : sortedKey)
  {
         System.debug('***************   Fianl Ordered MAP '+ accMap.get(finalK));
  }

 

I would definitly like this to work and marked as aceepted solution. Pease let me know is that you want.

LakshmanLakshman

Shashikant,

 

Your code fails when any two values in Map are same.

 

-Lakshman

Bramha1Bramha1

Hi Sharma,

 

  Will this work for the below Map.

 

accMap.put('ID1' , 20); 

accMap.put('ID2' , 10); 

accMap.put('ID3' , 40);

accMap.put('ID4' , 30); 

 accMap.put('ID5' , 50);

accMap.put('ID6' , 30); 

accMap.put('ID7' , 40); 

accMap.put('ID8' , 50); 


   

Thanks 

 

Bramha

 

 

 

 

Bramha1Bramha1

Hi Steve,

 

  I want the Keys to be sorted based on the Values(desc order like 10, 9, 8,7,6,5,4,3,2,1). After i am done with sorting i need to get the top 5 Values(10,9,8,7,6) Ids .

 

If you want any more info please do ask.

 

 

Thanks

 

Bramha

Ankit AroraAnkit Arora

If you are fetching this from query then instead of creating a map you should write the query accordingly. Like use DESC on your integer value in query and get the 5 records using Limit.

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

Bramha1Bramha1

Hi All,

 

 I have figured out the way and solved this issue. Thanks all of you guys who contributed as your ideas led to my result. 

 

Once again thanks for the help.

 

Cheers

Bramha

LakshmanLakshman

Bramha,

Curious to know your way.

 

-Lakshman

Bramha1Bramha1

}

 

Hi,

 

   I haven't got the output as a Map but could get the exact thing what i wanted in the order of  the Value. 

 

 

 

public void getTopDownlaodDocumentsForAccount(Id id) {

 

List<Research_Aggregator_Download__c> downloads = [Select Id,Name,Research_Aggregator_Document__c, Research_Aggregator_Document__r.Research_Id__r.Id fromResearch_Aggregator_Download__c where Research_Aggregator_Account__r.Account__r.Id=: id];  

accountMap = new Map<Id, Integer>();

if(downloads.size() > 0) {

for(Research_Aggregator_Download__c r : downloads) {

if(accountMap.containsKey(r.Research_Aggregator_Document__r.Research_Id__r.Id)) {

accountMap.put(r.Research_Aggregator_Document__r.Research_Id__r.Id, accountMap.get(r.Research_Aggregator_Document__r.Research_Id__r.Id)+1);

}else{

accountMap.put(r.Research_Aggregator_Document__r.Research_Id__r.Id, 1);

}

}

}

if(accountMap.size() > 0) getTopTenAccountDocumentDetails();

 

}

 

 

public void getTopTenAccountDocumentDetails() {

 

Map<Integer, Set<Id>> newMap = new Map<Integer, Set<Id>>();

Set<Id> accountIds = new Set<Id>();

accountList = new List<String>();

List<Integer> values = new List<Integer>(accountMap.Values());

for(Id accid : accountMap.keySet()) {

if(newMap.containsKey(accountMap.get(accid))) {

accountIds = newMap.get(accountMap.get(accid));

accountIds.add(accid);

newMap.put(accountMap.get(accid) ,accountIds );

else{

accountIds = new Set<Id>();

accountIds.add(accid);

newMap.put(accountMap.get(accid) , accountIds);

}

}

values.sort();

List<Integer> descValues = new List<Integer>();

for(Integer i = values.size()-1 ; i >= 0 ; i--) {

descValues.add(values.get(i));

}

 

Set<Id> Ids = new Set<Id>();

Set<Id> sortedIds = new Set<Id>();

Set<Id> idList = new Set<Id>();

for(Integer i : descValues) {

sortedIds = newMap.get(i);

idList.addAll(sortedIds);

if(idList.size() < 10 && !Ids.containsAll(sortedIds)) {

if(sortedIds.size() > 0) {

for(Id sorted : sortedIds) {

if(accountList.size() < 10)

accountList.add(sorted +','+ i);

}

}

 

 

Here i am using the accountList and getting the top 10 Values and in the next bit i am using a split to have the Id and the Integer Value.

 

NB: If you guys any sort of ideas to customize the code, please let me know.

 

 

Cheers

 

Bramha

Prateek.GuptaPrateek.Gupta

map<String , Integer> aMap = new Map<String,Integer>() ;
map<String , Integer> accMap = new Map<String,Integer>() ;
accMap.put('Id2' , 2);
accMap.put('Id1' , 1);
accMap.put('Id4' , 4);
accMap.put('Id3' , 3);
accMap.put('Id5' , 5);

List<String> aList = new List<String>();
List<integer> values = new List<integer>();

aList.addAll(accMap.keySet());
for(String str:aList)
{
values.add(accMap.get(str));
}
values.sort();

for(integer a: values)
{
for(String s:aList)
{
Integer j=accMap.get(s);
if(j==a)
{
aMap.put(s,j);
}
}
}
System.debug(aMap);

 

 

I know the complexity is greater in this case , but might be helpful with small Map

Sébastien RichardSébastien Richard
Hi, I understand your question because I faced the same problem

Input : collection of couple stored in map : A as key and B as value
- (A1, 100)
- (A2, 5)
- etc
- (An, 7)

Output : collection of couple sorted by value
- (5, A2)
- (7, An)
- etc
- (100, A1)

In my case, here is the map
Map<String, Decimal> mapConsultantTurnover = new Map<String, Decimal>();

the context of my application fills the map...

Here are the declaration to store ordered result :
 
public class Pair {
        public Decimal value { get; set; }
        public String key { get; set; }
        public Pair(Decimal value, String key) {
            this.value = value;
            this.key = key;
        }
}
 
List<Pair> oList = new List<Pair>();
for (String consultant: consultantSet) oList.add(new Pair(mapConsultantTurnover.get(consultant), consultant));
consultantSet contains all the keys

Bubble sort
Decimal tmpValue = 0.0;
String tmpKey = NULL;

// Bubble sort
for (Integer i = 0; i < oList.size()-1; i++) {
    for (Integer j = 1; j < oList.size(); j++) {
        if (oList.get(j-1).value > oList.get(j).value) {
            // permute
            tmpValue = oList.get(j-1).value;
            tmpKey = oList.get(j-1).key;
            oList.get(j-1).value = oList.get(j).value;
            oList.get(j-1).key = oList.get(j).key;
            oList.get(j).value = tmpValue;
            oList.get(j).key = tmpKey;
          }
     }
}

I hope this sample code can help.
 
Himanshu Rana 7Himanshu Rana 7
Map do not has  sorting support, they are a key value pair collection.
In apex to short a map we need to  use wrapper class and comparable interface
For more details go to :http://himanshurana.in/http-himanshurana-in-sort-map-in-apex-