1

Trying to form a two maps. One should contain only unique key and its values and another should have repeated keys and its values.

Name    Position

User1   Developer

User2   Designer

User3   Engineer

User1   Organiser

User2   Admin

First Map should contain only unique Names and its values.

For ex: Unique Map should have only,

User3=>Engineer

Second Map should contain only repeated Names and its values.

For ex: Repeated Map should have,

User1=>Developer, User2=>Designer, User1=>Organiser, User2=>Admin

IMP: Name field must be a key and Position should be a Value in map.

  • That's just how maps work. In every language I have ever worked with, anyway. – Adrian Larson Oct 27 '17 at 13:45
  • 2
    Not really sure why this one was closed. OP provided an example dataset, and examples of expected output. I'll admit some of the wording is unclear, but thinking of the example dataset as a List of SObjects makes the question pretty clear to me. – Derek F Oct 27 '17 at 17:06
4

This is not possible, maps do always have unique keys!

If you need multiple values for one key, you could save them in a list and add it to a map with the following structure:

List<String> positionsA = new List<String>{'Manager', 'Admin'};
Map<String, List<String>> positionsByName = new Map<String, List<String>>{'a' => positionsA };
3

Well, there's nothing built-in to Salesforce that would let you do this in a single line. There are probably a few different algorithms out there to accomplish this, but the first one that comes to mind for me is something like...

  • Iterate over your keys
  • If the key doesn't exist in the unique map, put in in the 'unique' map
  • Else, remove the key from the unique map, and put it in the 'repeated' map

You can't really know what is or is not unique until you iterate through everything.

About the only real challenge here is that you won't be able to store your initial key-value pairs in a map (because you'd end up overwriting the value stored by the key). A simple wrapper class would do the trick.

An example implementation

public class InitialWrapper{
    String key;
    String value;

    public InitialWrapper(String inKey, String inVal){
        key = inKey;
        value = inVal;
    }
}

List<InitialWrapper> initialCollection = new List<InitialWrapper>{
    new IntitialWrapper('User1', 'val1'),
    new IntitialWrapper('User2', 'val2'),
    new IntitialWrapper('User1', 'val3')
};

Map<String, String> uniqueMap = new Map<String, String>();

// The repeated map needs to hold a list of values rather than a single value
Map<String, List<String>> repeatedMap = new Map<String, List<String>>();

for(InitialWrapper iw :initialCollection){
    if(uniqueMap.containsKey(iw.key)){
        // In this block, we know the key is not unique (thanks to containsKey() )

        // We can't remove the repeated value yet; otherwise, the next time
        //   the same key comes up, we'll think it's unique again.
        String val = uniqueMap.get(iw.key);

        // We only want to put the value for the key we now know is not unique
        //   into repeatedMap's list of values once.
        // Probably the simplest way to do that is to add the value from the uniqueMap
        //   when we first add the key to repeatedMap
        if(!repeatedMap.containsKey(iw.key)){
            repeatedMap.put(iw.key, new List<String>{val});
        }

        repeatedMap.get(iw.key).add(iw.val);
    }else{
        // Nothing else to do for now but assume that the key is unique
        uniqueMap.put(iw.key, iw.val);
    }
}

As is, that example should give you a correct repeatedMap, but the uniqueMap will still have repeated keys in it.

The last step there would be to remove all keys (which in turn removes the values as well) from uniqueMap that exist in repeatedMap. Sets are built for that type of operation, and you could accomplish that in a single line using Salesforce-provided methods.

// map.keySet() returns a set containing all of the keys of the map (isn't it
//   nice when method names make sense like that?)
// Sets have a removeAll() method that removes all items in the set passed 
//   as a parameter from the set that called the method.
// Removing items from a map's keyset removes both the key and the value from the map
uniqueMap.keySet().removeAll(repeatedMap.keySet());

+edit:

Of course, if your data is coming from a collection of SObjects, then the wrapper class is unnecessary. Choose one field to be the key, another to be the value, and simply iterate over the collection of SObjects. iw.key is replaced with myObjectRec.some_field__c, and iw.value is replaced with myObjectRec.other_field__c.

  • uniqueMap will put a key which is incoming for the third time. As per the above code, the first key will be removed if there is repeat(second time). Since the key is removed, it will consider it as new key for the third time and will add it to the map. – mohammed azarudeen Oct 30 '17 at 12:40
  • @mohammedazarudeen Not if you remove the keys from uniqueMap outside of the loop. In fact, that's exactly why I didn't include uniqueMap.keySet().removeAll(repeatedMap.keySet()); inside the loop. – Derek F Oct 30 '17 at 13:02

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.