min2bro
min2bro

Reputation: 4638

Group By values in Python Dictionary

Dictionary contains block values in array, I have to group by 'blocks' and get the key which is smallest using lexicographically i.e using ASCII value of the characters and append to the list. for example in the below dict if we take block value [502698, 5067024] then BAYMON:6680:2 key should be appended in the list and for block [501930, 5025121] key GREYHORN:6679:2 should be appeneded in the list because that is smallest.

dict= 
    { 
            'BAYMON:6680:2': {'blocks': [502698, 5067024], 'cnt': 2}
            'GREYHORN:6679:2': {'blocks': [501930, 5025121], 'cnt': 2}
            'GREYHORN:6681:2': {'blocks': [501930, 5025121], 'cnt': 2}
            'GREYHORN:6680:2' :{'blocks': [501930, 5025121], 'cnt': 2}
            'GREYHORN:6679:2' : {'blocks': [501930, 5025121], 'cnt': 2}
            'BAYMON:6681:2' :{'blocks': [502698, 5067024], 'cnt': 2}
    }

list = ['BAYMON:6680:2','GREYHORN:6679:2']

Upvotes: 2

Views: 93

Answers (1)

Mateo
Mateo

Reputation: 1604

Here is a non-cryptic solution.

def smallest_key_by_blocks( dictio ) : 
    # mapping of blocks -> key 
    # will key the smallest key for each blocks
    smallest_dict = {}  

    for key, val in dictio.items() : 
        #convert to tuple so that we can use this as a key in dictionary
        blocks = tuple( val['blocks'] ) 

        if blocks not in smallest_dict : 
            # if no key seen so far for these blocks
            smallest_dict[ blocks ] = key 
        else : 
            # possibly update if the key is smaller 
            smallest_dict[ blocks ] = min( smallest_dict[blocks], key ) 

    return list( smallest_dict.values() )

Here is slightly more concise solution using the .get method on dictionaries...

def smallest_key_by_blocks_v1( dictio ) :         
    # mapping of blocks -> key 
    # will key the smallest key for each blocks
    smallest_dict = {}      
    for key, val in dictio.items() : 
        #convert to tuple so that we can use this as a key in dictionary
        blocks = tuple( val['blocks'] ) 
        key_sofar =  smallest_dict.get(blocks,key)
        smallest_dict[ blocks ] = min( key_sofar , key ) 

    return list( smallest_dict.values() )

A bit more concise and perhaps clearer ...:

def smallest_key_by_blocks_v2( dictio ) :         
    # first sort tuples of the form (key, blocks) 
    # then traverse and build the dictionary
    # .setdefault method guarantees that only the first key in the 
    # order will be assigned to blocks
    smallest_dict = {}
    sorted_tups = sorted( ( key, tuple(rec['blocks'])) 
                          for key, rec in dictio.items()   )
    for key, blocks in sorted_tups :
        smallest_dict.setdefault( blocks, key ) 

    return list( smallest_dict.values() )

Upvotes: 1

Related Questions