Найти в Дзене
BIMLAB

Linq в IronPython (СPython)

Как использовать Linq в IronPython при написании скриптов и макросов Revit (и не только) Подсказали Павел Алтынников, Igor и другие коллеги в этом тг-канале t.me/...apr Иногда, при разработке скриптов, возникает необходимость отфильтровать произвольным образом список собранных из документа Revit элементов. Возможности написать это лаконично открывает применение методов пространства имен System.Linq реализующие язык запросов к источнику данных Linq. Подробная статья про использование класса FilteredElementCollector на C# тут, на Python хорошее видео Эрика Фрица и статья на английском. Например, мы получаем из модели список элементов средствами Revit API и хотим получить список элементов, имеющих параметр по имени "имяПараметра". На C# это так: //doc - текущий документ Revit var els = new FilteredElementCollector(doc) //создает коллектор .WhereElementIsNotElementType() //фильтр "не является типом" .ToElements() //возвращает список элементов .Where(e => e.LookupParameter("имяП

Как использовать Linq в IronPython при написании скриптов и макросов Revit (и не только)

Подсказали Павел Алтынников, Igor и другие коллеги в этом тг-канале t.me/...apr

Иногда, при разработке скриптов, возникает необходимость отфильтровать произвольным образом список собранных из документа Revit элементов. Возможности написать это лаконично открывает применение методов пространства имен System.Linq реализующие язык запросов к источнику данных Linq.

Подробная статья про использование класса FilteredElementCollector на C# тут, на Python хорошее видео Эрика Фрица и статья на английском.

Например, мы получаем из модели список элементов средствами Revit API и хотим получить список элементов, имеющих параметр по имени "имяПараметра".

На C# это так:

//doc - текущий документ Revit
var els = new FilteredElementCollector(doc) //создает коллектор
.WhereElementIsNotElementType() //фильтр "не является типом"
.ToElements() //возвращает список элементов
.Where(e => e.LookupParameter("имяПараметра") is not null) //
.ToArray();

Метод Where пространства имен System.Linq применяется к списку элементов. В качестве аргумента получает булеву функцию (предикат), которая применяется к каждому элементу и определяет проходит условие элементе или нет. В нашем случае это наличие параметра с именем "имяПараметра". Предикат проверки записан в виде Лямбда-выражения.

На Python Лямбда-выражения записываются по-другому.

В нашем примере так:

lambda e: e.LookupParameter("имя_параметра") != None

Linq подключаем вот так:

import clr
clr.AddReference("System.Core")
import System
clr.ImportExtensions(System.Linq)

Переписываем на Pyhton:

#doc - текущий документ Revit
els = FilteredElementCollector(doc) \ #создает коллектор
.WhereElementIsNotElementType() \ #фильтр "не является типом"
.ToElements() \ #возвращает список элементов
.Where(lambda e: e.LookupParameter("имя_параметра") != None)

В примере показана простая проверка, можно сделать намного сложнее. Если дело не обойдется Лямбда-выражением, можно объявить более сложную логическую функцию, типа:

#содержит ли элемент в параметре "имя_параметра" значения "text_1" или "text_2"
def is_pass(el):
flag = False #флаг фильтра по умолчанию
param = el.LookupParameter("имя_параметра")
if param: #если найден параметр
val = param.AsValueString()
if "text_1" in val or "text_2" in val: #проверка на вхождения текстов
flag =True
return flag

Для выборки по этой функции (предикату) коллектор будет записан так:

#doc - текущий документ Revit
els = FilteredElementCollector(doc) \ #создает коллектор
.WhereElementIsNotElementType() \ #фильтр "не является типом"
.ToElements() \ #возвращает список элементов
.Where(is_pass) #выборка по предикату

Используя описанные методы, мы получаем большущие возможности по отбору интересующих нас элементов по различным критериям.

Пользуйтесь!

P.S. Надеюсь вы сами справитесь правильно расставить отступы в коде Python, Дзен их слопал...