Search code examples
pythonlistpython-3.xgroupingsublist

Python 3.x dynamically group elements in 2d list by common elements in list


[('20bgx6', 'HQ', 'Head Quarters'),
('2040bl', 'NVA', 'North Vietnamese Army '),
 ('2040bl', 'HEAT', 'High Explosive Anti Tank '),
 ('2040bl', 'HEAT', 'High Explosive Anti Tank '),
 ('202kon', 'HEAT', 'High Explosive Anti Tank '),
 ('202kon', 'EFP', 'Explosively Formed Penetrator/Projectile'),
 ('202kon', 'NCO', 'Non-commissioned officer'),
 ('202kon', 'MRAP', 'Mine Resistant Ambush Protected'),
 ('202kon', 'UXO', 'Unexploded Ordnance'),
 ('202kon', 'MP', 'Military Police'),
 ('202kon', 'CQ', 'Charge of Quarters'),
 ('202kon', 'HQ', 'Head Quarters'),
 ('202kon', 'NCO', 'Non-commissioned officer'),
 ('1zz081', 'BC', 'Battalion Commander'),
 ('1zz081', 'HMMWV', 'High Mobility Multi Wheeled Vehicle'),
 ('1zz081', 'SALUTE', 'Size Activity Location Uniform Time Equipment '),
 ('1zxpbs', 'NCO', 'Non-commissioned officer'),
 ('1ztrv6', 'SALUTE', 'Size Activity Location Uniform Time Equipment '),
 ('1ztrv6', 'HEAT', 'High Explosive Anti Tank '),
 ('1ztrv6', 'BDU', 'Battle Dress Uniform, predecessor to the ACU'),
 ('1zs9gz', 'AG', 'Adjutant General'),
 ('1zs9gz', 'HEAT', 'High Explosive Anti Tank ')]

I will have a list that is equal to that, and I need to group then such that there is groups of elements who all start with the same ID tag (2040bl, 202kon, etc) will be in their own sublist.

So the sub lists starting with '2040bl' will end up in their own group, all within the same list. The resulting list will have a resulting length of 7, as there is 7 unique ID tags (first element in each sublist)

I'm on python 3


Solution

  • You can use itertools.groupby method. With your data it seems it will work out of the box. For example:

    from itertools import groupby
    for k, v in groupby(l, key=lambda t: t[0])  # assuming your list is stored in l
        print('%s\n\t%s' % (k, list(v)))
    

    Will output:

    20bgx6
            [('20bgx6', 'HQ', 'Head Quarters')]
    2040bl
            [('2040bl', 'NVA', 'North Vietnamese Army '), ('2040bl', 'HEAT', 'High Explosive Anti Tank '), ('2040bl', 'HEAT', 'High Explosive Anti Tank ')]
    202kon
            [('202kon', 'HEAT', 'High Explosive Anti Tank '), ('202kon', 'EFP', 'Explosively Formed Penetrator/Projectile'), ('202kon', 'NCO', 'Non-commissioned officer'), ('202kon', '
    MRAP', 'Mine Resistant Ambush Protected'), ('202kon', 'UXO', 'Unexploded Ordnance'), ('202kon', 'MP', 'Military Police'), ('202kon', 'CQ', 'Charge of Quarters'), ('202kon', 'HQ', '
    Head Quarters'), ('202kon', 'NCO', 'Non-commissioned officer')]
    1zz081
            [('1zz081', 'BC', 'Battalion Commander'), ('1zz081', 'HMMWV', 'High Mobility Multi Wheeled Vehicle'), ('1zz081', 'SALUTE', 'Size Activity Location Uniform Time Equipment ')
    ]
    1zxpbs
            [('1zxpbs', 'NCO', 'Non-commissioned officer')]
    1ztrv6
            [('1ztrv6', 'SALUTE', 'Size Activity Location Uniform Time Equipment '), ('1ztrv6', 'HEAT', 'High Explosive Anti Tank '), ('1ztrv6', 'BDU', 'Battle Dress Uniform, predecess
    or to the ACU')]
    1zs9gz
            [('1zs9gz', 'AG', 'Adjutant General'), ('1zs9gz', 'HEAT', 'High Explosive Anti Tank ')]
    

    Important: When using groupby the data needs to be sorted by the group key, which in your example they are. Otherwise you can add a sorted(l, key=lambda t:t[0]) before grouping.