2011-02-26 102 views
0

這是一個簡單的腳本,我寫道:如何按v2.3中的第n個元素對列表進行排序?

#!/usr/bin/env python 

file = open('readFile.txt', 'r') 
lines = file.readlines() 
file.close() 
del file 

sortedList = sorted(lines, key=lambda lines: lines.split('\t')[-2]) 

file = open('outfile.txt', 'w') 
for line in sortedList: 
    file.write(line) 

file.close() 
del file 

改寫這樣的文件:

161788 group_monitor.sgmops 4530 1293840320 1293840152 
161789 group_atlas.atlas053 22350 1293840262 1293840152 
161790 group_alice.alice017 210  1293840254 1293840159 
161791 group_lhcb.pltlhc15  108277 1293949235 1293840159 
161792 group_atlas.sgmatlas 35349 1293840251 1293840160 

(其中最後兩個字段是劃時代的時間)的倒數第二場這個命令:

161792 group_atlas.sgmatlas 35349 1293840251 1293840160 
161790 group_alice.alice017 210  1293840254 1293840159 
161789 group_atlas.atlas053 22350 1293840262 1293840152 
161788 group_monitor.sgmops 4530 1293840320 1293840152 
161791 group_lhcb.pltlhc15  108277 1293949235 1293840159 

正如你所看到的,我用sorted(),這是在2.4版推出,我怎麼可以重寫劇本V2.3,所以它確實是 一樣。 另外,我想時代時間轉換爲人類可讀的格式,所以產生的文件看起來像這樣:

161792 group_atlas.sgmatlas 35349 01/01/11 00:04:11 01/01/11 00:02:40 
161790 group_alice.alice017 210  01/01/11 00:04:14 01/01/11 00:02:39 
161789 group_atlas.atlas053 22350 01/01/11 00:04:22 01/01/11 00:02:32 

我知道,這strftime("%d/%m/%y %H:%M:%S", gmtime())可以用來時代時間轉換,但我不能我不知道如何將它應用於腳本以該格式重寫文件。

評論?忠告珍惜!


@馬克:更新

在某些情況下,出現時間當屬3600,它是表示一個未竟的事業。我想打印中止而不是01/01/1970這樣一行。所以,我改變了這樣的format_seconds_since_epoch()

def format_seconds_since_epoch(t): 
    if t == 3600: 
     return "aborted" 
    else: 
     return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple()) 

它解決了這個問題。在這方面能做到最好嗎?乾杯!!

回答

4
file = open('readFile.txt', 'r') 
lines = file.readlines() 
file.close() 
del file 

lines = [line.split(' ') for line in lines] 
lines.sort(lambda x,y: cmp(x[2], y[2]) 
lines = [' '.join(line) for line in lines] 
+0

幾件小事情:1.OP的文件被標籤分隔而不是單個空格2.您需要比較倒數第二列,而不是第三列3.最好將列值轉換爲數字在比較之前,以防萬一某些值是2001年9月以前的時間:) – 2011-02-26 11:06:06

1

在回答你的最後的查詢,可以「自紀元秒」值使用datetime.fromtimestamp創建從time_t樣一個datetime對象,例如

from datetime import datetime 
from time import strftime 

def format_seconds_since_epoch(t): 
    return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple()) 

print format_seconds_since_epoch(1293840160) 

因此,把與的pynator's answer略加修改在一起,你的腳本可能類似於:

#!/usr/bin/env python 

from datetime import datetime 
from time import strftime 
import os 

def format_seconds_since_epoch(t): 
    return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple()) 

fin = open('readFile.txt', 'r') 
lines = fin.readlines() 
fin.close() 
del fin 

split_lines = [ line.split("\t") for line in lines ] 

split_lines.sort(lambda a, b: cmp(int(a[-2]),int(b[-2]))) 

fout = open('outfile.txt', 'w') 
for split_line in split_lines: 
    for i in (-2,-1): 
     split_line[i] = format_seconds_since_epoch(int(split_line[i])) 
    fout.write("\t".join(split_line)+os.linesep) 

fout.close() 
del fout 

注意,使用file作爲變量名是一個壞主意,因爲它屏蔽了該內置file類型,所以我將它們改爲finfout。 (即使你是del荷蘭國際集團的變量之後,它仍然是良好的作風,以避免名稱file,我想。)

在回答你關於特殊的「3600」的價值進一步的問題,您的解決方案是好的。就個人而言,我可能會保留format_seconds_since_epoch函數,因此它不會有令人驚訝的特殊情況,並且通常更有用。你可以創建一個特殊的情況下,另外的包裝功能,或者只是改變split_line[i] = format_seconds_since_epoch(int(split_line[i]))行:

entry = int(split_line[i]) 
if entry == 3600: 
    split_line[i] = "aborted" 
else: 
    split_line[i] = format_seconds_since_epoch(entry) 

...但是,我不認爲還有很多的差異。順便說一句,如果這不僅僅是一次性的任務,我會看到你是否可以在2系列中使用比2.3更高版本的Python,而現在它已經很老了 - 它們有很多很棒的功能可以幫助你一個寫清潔腳本。

+1

@ mark:非常感謝。稍後我會測試腳本(生成實際輸入文件需要一些時間)並在稍後報告。是的,使用'file'作爲變量名是個壞主意,確實是我的錯。謝謝指出。乾杯!! – MacUsers 2011-02-26 11:11:40

+0

@標誌:它工作得很好。感謝您的快速回放。乾杯!! – MacUsers 2011-02-26 14:57:09

+0

@mark:嗯,只是一個小問題:有時候,最後一個字段是「3600」,這意味着特定的工作沒有成功完成。如何打印例如「中止」,而不是「01/01/70 02:00:00」這樣一行?乾杯!! – MacUsers 2011-02-26 15:36:52

相關問題