Ошибка типа: строковые индексы должны быть целыми числами при использовании itemgetter со строковым аргументом

#python #sorting #ifc

#python #сортировка #ifc

Вопрос:

Я пытаюсь добиться категоризации модели IFC с использованием IfcOpenShell.

На первом шаге я извлекаю атрибуты GlobalId и ObjectType из списка элементов модели IFC. Затем я хотел бы отсортировать информацию, используя ObjectType атрибут, чтобы получить следующую информацию из модели:

 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'}
 

Элементы с одинаковыми ObjectType и разными GlobalId должны быть объединены в одну группу, чтобы получить классификацию.

 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)
 

С приведенным выше кодом я получаю сообщение об ошибке Exception has occurred: TypeError string indices must be integers .

Ответ №1:

В первом цикле вы собираете элементы rows в виде строк в форме '3vpWoB...: Basiswand...' . Например:

 ['3vpWoB_K1EZ8RCaYmNGs6M: Basiswand:Bestand 08.0:161894',
 '3vpWoB_K1EZ8RCaYmNGsB2: Basiswand:Bestand 08.0:161894',
 '3vpWoB_K1EZ8RCaYmNGssv: Fenster 1-flg - Variabel',
 '3vpWoB_K1EZ8RCaYmNGsqI: Fenster 1-flg - Variabel'
]
 

Затем, когда вы сортируете и группируете с itemgetter помощью функции as key, вам нужно будет указать позицию или диапазон в строке. Например. когда вы хотите сравнить на основе использования 24-го символа itemgetter(24) или аналогично сравнить на основе использования конечной подстроки itemgetter(slice(24,-1)) .

 >>> '3vpWoB_K1EZ8RCaYmNGs6M: Basiswand:Bestand 08.0:161894'[24]
'B'
>>> '3vpWoB_K1EZ8RCaYmNGs6M: Basiswand:Bestand 08.0:161894'[24:-1]
'Basiswand:Bestand 08.0:161894'
 

Если вы попытаетесь использовать строку в качестве индекса для получения подстроки, как в itemgetter('IfcBuildingElement') , вы получите ошибку, которую вы видите.

 >>> '3vpWoB_K1EZ8RCaYmNGs6M: Basiswand:Bestand 08.0:161894'['IfcBuildingElement']
TypeError: string indices must be integers 
 

Итак, чтобы успешно использовать itemgetter('Element') as key для сортировки и группировки, вы хотите собирать строки как словари вида
{'GlobalId': '3vpWoB...', 'Element': 'Basiswand...'} вместо строк. Например:

 [{'GlobalId':'3vpWoB_K1EZ8RCaYmNGs6M', 'Element':'Basiswand:Bestand 08.0:161894'},
 {'GlobalId':'3vpWoB_K1EZ8RCaYmNGsB2', 'Element':'Basiswand:Bestand 08.0:161894'},
 {'GlobalId':'3vpWoB_K1EZ8RCaYmNGssv', 'Element':'Fenster 1-flg - Variabel'},
 {'GlobalId':'3vpWoB_K1EZ8RCaYmNGsqI', 'Element':'Fenster 1-flg - Variabel'}
]
 

Это может быть достигнуто с помощью следующего кода в цикле для сбора строк.

 rows.append({'GlobalId': buildingelement.GlobalId, 'Element': buildingelement.ObjectType})