2013-08-03 2 views
1

Я знаю некоторые основы в C++, но я новичок в python.python 2.7 - переупорядочить вывод списков с новым ограничением 'order'

У меня есть кусок рабочего кода (см ниже), и я хотел бы добавить ограничение для форматирования своего вывода, и я не могу понять, как это сделать ...

Позволь мне объяснить что делает программа:

у меня есть входной файл colors.csv, который содержит список цветов, один цвет линии: цвета определяются их именем и колориметрические координаты X, Y и Z, это выглядит так:

Colorname, X1, Y1, Z1 
Colorname2, X2, Y2, Z2 
...etc. 

Учитывая любой список XYZ координат, содержащимся в другом входном файле targets.csv программа даст мне список решений в выходном файле output.txt

Это решение вычисляется по первой триангуляции точек облака с tetgen и затем барицентрическими координатами точка в тетраэдре, (но это не дело, чтобы объяснить все здесь ...)

решения имеет вид:

target, name0, density0, name1, density1, name2, density2, name3, density3 

есть всегда только 4 имен и связанные с ними плотность.

Это будет выглядеть, например, так:

122 ,PINKwA,0.202566115168,GB,0.718785775317,PINK,0.0647284446787,TUwA,0.0139196648363 

123 ,PINKwA,0.200786239192,GB,0.723766147717,PINK,0.0673550497794,TUwA,0.00809256331169 

124 ,PINKwA,0.19900636349,GB,0.72874651935,PINK,0.0699816544755,TUwA,0.00226546268446 

125 ,OR0A,0.00155317194109,PINK,0.0716160265958,PINKwA,0.195962072115,GB,0.730868729348 

126 ,OR0A,0.00409427478508,PINK,0.0726192660009,PINKwA,0.192113520109,GB,0.731172939105 

127 ,OR0A,0.00663537762906,PINK,0.073622505406,PINKwA,0.188264968103,GB,0.731477148862 

То, что я хотел бы сделать сейчас?

По практическим соображениям, я хотел бы, чтобы мой результат соответствовал определенному заказу. Мне нужен «список приоритетов» для управления порядком вывода name, density.

Мой фактический выход программы цвет названия в порядке, что я не понимаю, но в любом случае мне нужно эти названия цветов, чтобы быть в определенном порядке, например PINK всегда должен быть первым PINKwA второй, и т.д.

Вместо:

127 ,OR0A,0.00663537762906,PINK,0.073622505406,PINKwA,0.188264968103,GB,0.731477148862 

Я хочу;

127 ,PINK,0.073622505406,PINKwA,0.188264968103,OR0A,0.00663537762906,GB,0.731477148862 

Поскольку мой список приоритетов говорит:

0, PINK 
1, PINKwA 
2, OR0A 
3, GB 

Как я мог просто добавить эту функцию в коде ниже? Есть идеи?

EDITED КОД (работает ...):

import tetgen, geometry 
from pprint import pprint 
import random, csv 
import numpy as np 
from pprint import pprint 

all_colors = [(name, float(X), float(Y), float(Z)) 
       for name, X, Y, Z in csv.reader(open('colors.csv'))] 

priority_list = {name: int(i) 
       for i, name in csv.reader(open('priority.csv'))} 

# background is marked SUPPORT 
support_i = [i for i, color in enumerate(all_colors) if color[0] == 'SUPPORT'] 
if len(support_i)>0: 
    support = np.array(all_colors[support_i[0]][1:]) 
    del all_colors[support_i[0]] 
else: 
    support = None 

tg, hull_i = geometry.tetgen_of_hull([(X,Y,Z) for name, X, Y, Z in all_colors]) 
colors = [all_colors[i] for i in hull_i] 

print ("thrown out: " 
     + ", ".join(set(zip(*all_colors)[0]).difference(zip(*colors)[0]))) 

targets = [(name, float(X), float(Y), float(Z), float(BG)) 
      for name, X, Y, Z, BG in csv.reader(open('targets.csv'))] 

for target in targets: 
    name, X, Y, Z, BG = target 
    target_point = support + (np.array([X,Y,Z]) - support)/(1-BG) 
    tet_i, bcoords = geometry.containing_tet(tg, target_point) 

    output = open('output.txt','a') 

    if tet_i == None: 
     output.write(str(target[0])) 
     output.write('\n') 


    else: 
     names = [colors[i][0] for i in tg.tets[tet_i]] 
     sorted_indices = sorted(enumerate(names), key=lambda (i, name): priority_list[name]) 
     output.write(target[0]) 
     counting = 0 

     for i, name in sorted(enumerate(names), key=lambda (i, name): priority_list[name]): 
      output.write(',%s,%s' % (name, bcoords[i])) 
      counting = counting + 1 

      if counting > 3: 
       output.write('\n') 
       counting = 0 

output.close() 

ответ

1

Во-первых, вам нужно закодировать ваш список приоритетов непосредственно в коде Python:

priority_list = { 
    'PINK': 0, 
    'PINKwA': 1, 
    'OR0A': 2, 
    'GB': 3, 
} 

Это позволит вам быстро получить заказ для заданного имени цвета.Затем вы можете использовать аргумент key для sorted, чтобы отсортировать ваши имена по их приоритету. Критически, однако, вам нужно получить не отсортированные имена, а индексы отсортированных имен, похожие на http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html.

sorted_indices = sorted(enumerate(names), key=lambda (i, name): priority_list[name]) 

enumerate помечает каждое встроенное имя с индексом в исходном списке имен, а затем sorted BUILTIN сортирует в результате (i, name) пары, основанной на их ранге в списке приоритетов. Затем мы можем записать имена в файл, а затем соответствующий элемент (используя значение индекса) из массива bcoords.

for i, name in sorted_indices: 
    output.write(',%s,%s' % (name, bcoords[i])) 

Итак, вот что я хотел бы сделать окончательный блок в вашем коде выглядит следующим образом:

names = [colors[i][0] for i in tg.tets[tet_i]] 
output.write(target[0]) 
for i, name in sorted(enumerate(names), key=lambda (i, name): priority_list[name]): 
    output.write(',%s,%s' % (name, bcoords[i])) 
output.write('\r\n') 
output.close() 

Здесь я изменил свою выходную стратегию файла, чтобы быть немного больше Pythonic - в общем, добавив, строки в основном не выполняются, лучше вместо этого создать строку формата и заполнить переменные (вы также можете использовать .format() для строки). Кроме того, вы можете совершать несколько вызовов до .write(), и они просто будут продолжать писать байты в файл, поэтому нет необходимости создавать большую длинную строку сразу для записи. Наконец, не нужно звонить str на '\r\n', так как это уже строка.

+0

Спасибо, это здорово! Чтобы использовать CSV-файл в качестве моего 'priority_list', я могу использовать:' priority_list = csv.reader (open ('priority.csv')) '?? Где я должен вставить эту строку? –

+1

Это зависит от структуры вашего CSV-файла. Если он имеет такую ​​же форму, как вы указали выше, то я бы преобразовал его в словарь с помощью 'priority_list = {name: int (i) для i, name в csv.reader (open ('priority.csv'))} '. – lmjohns3

+0

Привет, со мной что-то не так: я обновил код, но я должен был совершить ошибку. Я редактировал код выше и добавил ошибку сообщения в конце: 'TypeError: () принимает ровно 2 аргумента (1 задано)' –

Смежные вопросы