I am trying to achieve categorisation of an IFC model using IfcOpenShell.
In the first step I extract the the attributes GlobalId  and ObjectType from a list of IFC model elements. Then I would like to sort the information using the ObjectType attribute, to receive the following information from the model:
Basiswand:Bestand 08.0:161894
    {'GlobalId': '3vpWoB_K1EZ8RCaYmNGs6M', 'Element': 'Basiswand:Bestand 08.0:161894'}
    {'GlobalId': '3vpWoB_K1EZ8RCaYmNGsB2', 'Element': 'Basiswand:Bestand 08.0:161894'}
Fenster 1-flg - Variabel
    {'GlobalId': '3vpWoB_K1EZ8RCaYmNGssv', 'Element': 'Fenster 1-flg - Variabel'}
    {'GlobalId': '3vpWoB_K1EZ8RCaYmNGsqI', 'Element': 'Fenster 1-flg - Variabel'}
The elements with same ObjectType and with different GlobalId should be combined in one group, to get a categorisation.
rows =[]   
buildingelement = model.by_type('IfcBuildingElement')
for buildingelement in model.by_type('IfcBuildingElement'):
    rows.append(str(buildingelement.GlobalId) + ': ' + str(buildingelement.ObjectType))
print(rows)
from operator import itemgetter 
from itertools import groupby
    # Sort by the desired field first
rows.sort(key=itemgetter('IfcBuildingElement'))
    # Iterate in groups
for date, items in groupby(rows, key=itemgetter('IfcBuildingElement')): 
    print(date)
    for i in items: 
        print(' ', i)
With above code, I get the error message Exception has occurred: TypeError string indices must be integers.
 
                        
In the first loop, you collect the elements of
rowsas strings in the form'3vpWoB...: Basiswand...'. For example:Then, when you sort and group with
itemgetteras key function, you would have to specify a position or range in the string. E.g. when you want to compare based on the 24th character useitemgetter(24)or likewise to compare based on the trailing substring useitemgetter(slice(24,-1)).If you try to use a string as index to get a substring, like in
itemgetter('IfcBuildingElement')you get the error you see.So in order to successfully use
itemgetter('Element')as key for sorting and grouping, you want to collect the rows as dictionaries of the form{'GlobalId': '3vpWoB...', 'Element': 'Basiswand...'}instead of strings. For example:This could be achieved with the following code in the loop to collect the rows.