среда, 2 марта 2016 г.

Алгоритм сортировки данных в Revit. Часть 1

             Все мы видели вот такую таблицу в семи нами "любимой" программе Revit :

 

             Она отвечает за сортировку данных в спецификации, но в силу того что у нас только 4 возможных варианта сортировки данных мы не можем выполнить ряд задач. Таких как спецификация металлопроката или спецификация АС или банальная ведомость деталей.  Кто нибудь задавался вопросом как это работает ?
             Для полного понимания этой статьи конечно же необходимо понимание основ программирования. Я покажу лишь часть самого алгоритма без всякой чепухи , например как выдрать все нам необходимые данные из Revit и после обработки поместить в нужное место в том же Revit. Только математика и только логика.
             Допустим у нас есть 8 арматурных стержней , разного диаметра , разного типа , разной длинны и количества. Попробуем отсортировать эти данные, и так у нас есть список длин:

ARMdlina=(1200,2000,2000,1200,3000,5000,1500,3000)

Теперь зададимся диаметрами:

ARMdiametr=(12,20,20,16,8,10,10,8)

Теперь нам необходимо отсортировать эти данные например по диаметру в порядке возрастания, тоесть если мыслить таблицей Revit то мы хотим получить такое :


        И что же нам необходимо для выполнения такой простой сортировки ? ничего особенного , только знание полного синтаксиса Python или иного языка. Создадим функцию высшего порядка из булевого выражения:

 new_list2 = [(c1,d1) for c1,d1 in zip(ARMdiametr,ARMdlina)]

         Я думаю погуглив что есть ZIP в Python вы все поймете. Если выполнить кусок получившегося кода мы получим следующее:


              Как видно мы просто объединили списки в одни. Каждый i-тый член списка сложился с j-тый членом второго списка. Теперь мы можем упорядочить элементы внутри списка как нам нужно.
              А нам нужно просто узнать количество каждого типа с одинаковой длинной и диаметром и отсортировать по порядку все элементы. Для этого выполним двух уровневый цикл по новому списку new_list2 и будем отсеивать все повторяющиеся элементы и одновременно считать число их повторов (это и будет число экземпляров) , итак запишем код:

 

            В итоге мы получили список количества каждого экземпляра  [1, 2, 1, 2, 1] и сами экземпляры [(12, 1200), (20, 2000), (16, 1200), (8, 3000), (10, 5000)]. НО давайте пересчитаем изначальный список , в нем 8 элементов списка , а нам циклы вернули всего лишь 1+2+1+2+1=7, где то завалялся один элемент. этот элемент с диаметром 10 и длиной 1500. Он седьмой в первоначальной списке.
             Не знаю на сколько я прав , но с точки зрения кода вроде все верно , нету "лозеек". Но один элемент потерялся. Я нашел этой проблеме решение , просто скопировал весь цикл еще раз и пособирал "яблоки" которые выпали из корзинки:

   

Как видно к нам вернулся блудливый сын и вся семья опять вместе.

 Вот и сказочке конец :)

4 комментария:

  1. Выполнять цикл for по списку, в котором при этом удаляются элементы не самая лучшая идея, так как for создаёт итератор, по каждому члену которого и проходится, т.е. при удалении первого элемента списка цикл начнёт следующую итерацию не сначала, а со второго элемента, поэтому и происходит выпадение элементов. Можно попробовать решить через while. Например, так:
    cnt, nm = [], []
    nm_i = tuple()
    while new_list2:
    cnt.append(new_list2.count(new_list2[0]))
    i = new_list2[0]
    nm.append(i)
    while i in new_list2:
    new_list2.remove(i)
    print(cnt)
    print(nm)

    ОтветитьУдалить
  2. С отступами
    http://joxi.ru/KAxzK5dI4RyMMm

    ОтветитьУдалить
  3. ну он не совсем выпадает , он просто не доходит до конца списка, через For я и создал так чтобы он выдрал все повторяющиеся элементы и опять начал с начала , но я так понимаю когда он доходит до момента когда в списке всего лишь один элемент он останавливается в итоге еще одним циклом я добираю "остатки". Еще не посмотрел ваш вариант но через while пробовал когда то.

    ОтветитьУдалить

Поиск по этому блогу