2013-08-03 19 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 

怎麼可能,我只是這個功能添加到下面的代碼?任何想法?

編輯的代碼(的作品...):

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內置排序產生的根據自己的優先級列表排名(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() 

在這裏,我改變了你的文件輸出戰略是多一點Python的 - 一般來說,加字符串在很大程度上沒有完成,最好是創建一個格式字符串並填入變量(您也可以使用字符串上的.format()來完成此操作)。此外,您可以對.write()進行多次調用,並且它們將繼續向該文件寫入字節,因此不需要一次創建一個大的長字符串來寫出。最後,不需要在'\r\n'上調用str,因爲它已經是一個字符串。

+0

謝謝,太好了!要使用.csv文件作爲我的'priority_list',我可以使用:'priority_list = csv.reader(open('priority.csv'))'?我應該在哪裏插入這條線? –

+1

這取決於您的.csv文件的結構。如果它與上面列出的形式相同,那麼我會將它轉換爲字典,使用'priority_list = {name:int(i)for i,name in csv.reader(open('priority.csv'))} '。 – lmjohns3

+0

嗨,我錯了:我更新了代碼,但我應該犯了一個錯誤。我編輯了上面的代碼,並在末尾添加了消息錯誤:'TypeError:()需要恰好2個參數(給出1)' –