In [1]: data = [ row.split() for row in '''\ ...: test1 ERROR1 ERROR1:TYPE1 ...: test2 ERROR1 ERROR1:TYPE2 ...: test3 ERROR2 ERROR2:TYPE1 ...: test4 ERROR1 ERROR1:TYPE1 ...: test5 ERROR2 ERROR2:TYPE1 ...: test6 ERROR2 ERROR2:TYPE2'''.split('\n')] In [2]: data Out[2]: [['test1', 'ERROR1', 'ERROR1:TYPE1'], ['test2', 'ERROR1', 'ERROR1:TYPE2'], ['test3', 'ERROR2', 'ERROR2:TYPE1'], ['test4', 'ERROR1', 'ERROR1:TYPE1'], ['test5', 'ERROR2', 'ERROR2:TYPE1'], ['test6', 'ERROR2', 'ERROR2:TYPE2']] In [3]: nested = {} In [4]: for file, error, errortype in data: ...: nested.setdefault(error, {}).setdefault(errortype, []).append(file) ...: In [5]: nested Out[5]: {'ERROR1': {'ERROR1:TYPE1': ['test1', 'test4'], 'ERROR1:TYPE2': ['test2']}, 'ERROR2': {'ERROR2:TYPE1': ['test3', 'test5'], 'ERROR2:TYPE2': ['test6']}} In [6]: for error, errortypes in sorted(nested.items()): ...: print('\n##', error) ...: for errort, tests in sorted(errortypes.items()): ...: print('#', errort) ...: print(', '.join(tests)) ...: ## ERROR1 # ERROR1:TYPE1 test1, test4 # ERROR1:TYPE2 test2 ## ERROR2 # ERROR2:TYPE1 test3, test5 # ERROR2:TYPE2 test6 In [7]: