2013-06-01 41 views
2

我有一個變量compareout存儲數據的嵌套列表:我想的Python:串聯和格式化字符串/花車同時寫入到CSV

compareout = [... 
[Guyana,951.723423,1037.123424,28.476757,2.991234], 
[Bolivia,936.123420,1065.8234236,43.25123,4.62], 
[Philippines,925.52342342,1119.62342341,64.70234234,6.991234123], 
[Congo (Rep.),907.22342343,1657.52342349,250.1242342,27.571234123], 
...] 

  1. 排序由第二列升序,將此排序列表的前10個項目寫入.csv
  2. 按第二列降序排序,將此前10個項目排序列表寫入第二個.csv

然而,我需要格式化輸出,使得所有的浮體只有2位小數,和contcatenate USD到第二和第三列中的值的前面,並添加「%」符號的最後一列的端部值。雖然我可以遍歷「compareout」並替換最後兩個colums是這樣的...

for line in compareout: 
    avgyrincr = (float(line[2])-float(line[1]))/3 
    percent = (avgyrincr/float(line[1])) * 100 
    line.append("%.2f" % avgyrincr) 
    line.append("%.2f%%" % percent) 

我不能做這樣簡單的東西:

for line in ascending: 
    line[1] = "USD %.2f" % line[1] 
    line[2] = "USD %.2f" % line[2] 

,因爲這不允許排序。目前我有上面的代碼發生在我第一次對第一個文件進行排序和寫入數據之後,但當然我不能按降序排序......另外,我對如何僅指定寫入10個項目感到困惑。 ..

我已經搜索了大約一個小時,似乎無法找到足夠的信息,以確定csv.writerow()函數是否允許在編寫時格式化,並且我已經用完了方法。如果有人能夠給我一些想法,我會最欣賞...

回答

2

您可以編寫一個format功能,從你的列表需要一個項,並返回格式化行。喜歡的東西:

def format_row(row): 
    result = row[:] #make a copy of the row 
    # format should be preferred over %. 
    # Also, you don't have to escape the %. 
    result[1] = "USD {:.2f}".format(result[1]) 
    result[2] = "USD {:.2f}".format(result[2]) 
    # do whatever else you have to do for a single row 
    return result 

之後,你可以這樣做:

sorted_values = sorted(the_values, key=lambda x: x[1]) #sort by second column 
formatted_lines = (format_row(row) for row in sorted_values[:10]) 
for line in formatted_lines: 
    writer.writerow(line) 

#[-10:] -> take last 10 elements, [::-1] reverse the order 
other_lines = (format_row(row) for row in sorted_values[-10:][::-1]) 
for line in other_lines: 
    writer.writerow(line) 

注意,調用compareout名單上兩次sorted需要兩倍的時間,而使用sorted_values[-10:][::-1]需要一定的時間,和因此效率更高。如果你仍然想使用兩類,我建議你做這樣的事情:

sorted_values = sorted(the_values, key=lambda x: x[1]) #sort by second column 
# ... 
#use sorted_values, instead of the_values 
sorted_values.sort(key=lambda x: x[1], reverse=True) 
# ... 

即致電.sort上已經排序值。

>>> import random 
>>> L = [random.randint(0, 1000) for _ in range(10000)] 
>>> import timeit 
>>> timeit.timeit('sorted(L)', 'from __main__ import L', number=100) 
0.2509651184082031 
>>> timeit.timeit('sorted(L)', 'from __main__ import L', number=100) 
0.2547318935394287 
>>> L.sort() 
>>> timeit.timeit('sorted(L, reverse=True)', 'from __main__ import L', number=100) 
0.11794304847717285 
>>> timeit.timeit('sorted(L, reverse=True)', 'from __main__ import L', number=100) 
0.11488604545593262 

(在這個簡單的例子,你可以使用:使用部分排序的數據處理時,因此上面的代碼將採取O(nlogn)爲第一個排序,只有O(n)第二列表的排序算法是很聰明reversed(L),但在其他情況下是不可能的)。

+0

謝謝!這是一種享受。我注意到第二個輸出的'other_lines =(format_row(row)in sorted_values [: - 10] [:: - 1])'對我來說並不適用,所以我用'sorted_values = sorted(compareout,key = operator.itemgetter(1),reverse = True)\ other_lines =(format_row(row)for sorted_values [:10])' – Rookierookie

+0

@Rookierookie D'oh!我在評論中正確地寫了它,但不是在代碼中。 '-10'應該在*之前*指定最後十個元素。固定。 – Bakuriu

0

考慮建立兩個不同的對象列表;對它們進行排序相應然後writerow()各行成csv文件,分別

排序(輸出,鍵= itemgetter(0,1))#例如,排序,通過使用操作者的列0,則1列表對象。itemgetter()

嘗試添加反向= True以上述排序()函數,因爲要writerow()僅10個項目爲每個輸出文件,審查csvreader.line_num或者使用與csvreader循環降序排序

未來()