2012-08-03 55 views
5

因此,我想要做的事似乎比較簡單,但對於我的生活而言,我無法完全理解它。我有一個像將字符串列表保留爲python的格式

4 2 
6 5 1 
9 4 5 

一個txt文件,我想它的信息提供給我,像這樣(即我不需要寫一個新的.txt文件,除非它是必要的。)...

3 1 
5 4 0 
8 3 4 

或者,從每個數字中減去1,但格式保持不變。原文中永遠不會有大於1的數字,所以不可能有負數。這整個頭痛是由於轉換索引開始0而不是1。可什麼複雜的事情是,原來的文件打印像

['4 2 /n','6 5 1 /n', '9 4 5 /n'] 

我已經完成

那麼它的different東西混雜我在計算器上已經found,但我想我會關於它可能是最麻煩的方式。和this一個沒有任何意義,當我實現它。雖然它可以是相同的軌跡和與空間問題上..

origianl = open(file, 'r') 
for line in original.readlines(): 
    newline = line.replace(" \n","") 
    finalWithStrings.append(newline) 

finalWithIntegers = [map(int,x) for x in finalWithStrings] 
finalWithIntegers[:] = [x-1 for x in finalWithIntegers] 

我的思維過程是,我需要刪除「/ N」並將這些字符串轉換爲整數,這樣我就可以從中減去1。並以某種方式保持格式。由於每行包含有關另一個文件的類似索引的行的信息,因此格式化必須相同。我不想在最終結果(或打印語句)中看到「/ n」,但我仍然想要新行開始的效果。但是,上面的代碼不會有兩個原因(我知道的)。

int(n[:])拋出一個錯誤,因爲它不喜歡的空間,當我把一個值(比如0)在那裏,然後代碼打印每行的第一個數字,並減去一..並把它所有在一條線上。

[3, 5, 8] 

因此,它似乎是多餘的拿出一個回車,不得不扔在另一個,但我確實需要保留原來的格式,以及有辦法讓所有的數字!

這也沒有工作:

for line in original.readlines(): 
    newline = line.replace(" \n","") 
    finalWithStrings.append(newline) 

finalWithIntegers = [map(int,x) for x in finalWithStrings] 
finalWithIntegers[:] = [x-1 for x in finalWithIntegers]  

但不是隻是一個錯誤的輸出,這是一個錯誤:

ValueError:invalid literal for int() with base 10:'' 

有沒有人對我做錯了什麼在這裏的任何想法以及如何解決這個問題?我正在使用Python 2.6並且是初學者。

回答

9
with open("original_filename") as original: 
    for line in original: 
     #if you just want the line as integers: 
     integers = [ int(i) - 1 for i in line.split() ] 
     #do something with integers here ... 

     #if you want to write a new file, use the code below: 
     #new_line = " ".join([ str(int(i) - 1) for i in line.split() ]) 
     #newfile.write(new_line + '\n') 

我已經在上面的示例中的上下文管理器中打開了您的文件,因爲這是很好的做法(從版本2.5開始)。上下文管理器確保您退出該上下文時文件已正確關閉。

編輯

它看起來像你可能會想創建一個二維列表...要做到這一點,像這樣的工作:

data = [] 
with open("original_filename") as original: 
    for line in original: 
     integers = [ int(i) - 1 for i in line.split() ] 
     data.append(integers) 

或者,如果你喜歡的1班輪(我沒有):

with open("original_filename") as original: 
    data = [ [int(i) for i in line.split()] for line in original ] 

現在,如果你打印:

for lst in data: 
    print (lst) # [3, 1] 
        # [5, 4, 0] 
        # [8, 3, 4] 
+0

完美,這正是我一直在尋找的!感謝您的編輯..它更具體到我所需要的。 – Ason 2012-08-03 17:43:18

+0

@Ason - 沒問題。我會更仔細地重新閱讀您的文章,並發現您不需要在新文件中使用該文件,除非這是實現此目的的最簡單方法。所以,我更新了。 – mgilson 2012-08-03 17:45:53

+0

+1我很欣賞你花時間回答! – Ason 2012-08-03 17:47:33

4

下面是使用正則表達式完成此操作的非常簡單的方法。這裏的好處是,格式是保證留一模一樣的,因爲它將取代到位的數字不接觸任何空白:

import re 

def sub_one_repl(match): 
    return str(int(match.group(0))-1) 

for line in original.readlines(): 
    newline = re.sub(r'\d+', sub_one_repl, line).rstrip('\n') 
+0

非常感謝您的回答!我對正則表達式不是很熟悉,所以我必須選擇一個不同的答案,因爲它更容易理解和實現......但+1幫助未來的訪問者! – Ason 2012-08-03 17:46:42

+0

好主意,雖然我認爲你的意思是'match.group'而不是'm.group'。同樣,你可能想讓'sub_one_repl'更安全一些(即,如果正則表達式不匹配.group會導致異常)或者只是做一個lambda。你也可以將它作爲list comp或者generator表達式:'(re.sub(r'\ d +',lambda m:str(int(m.group(0)) - 1),line) .readlines())' – 2012-08-03 18:17:50

+1

@AdamParkin - 謝謝,我最初有'm'作爲參數並忘記更新函數。 'sub_one_repl'只會在匹配成功時被調用,它們總是全部數字,所以它應該是安全的。單行是一個選項,但我仍然會將'lambda'移到它外面,所以您不會在每次迭代時重新創建函數。 – 2012-08-03 18:48:31

0

試試這個:

with open(filepath) as f: 
    for line in f: 
     print " ".join([str(int(i)-1) for i in line.split()]) 

希望幫助

+0

你說得對。答案已更新 – inspectorG4dget 2012-08-03 17:46:30

2

另一種方法是使用csv模塊和列表理解:

from csv import reader 

data = [[int(j) - 1 for j in i] for i in reader(open("your_file"), delimiter=' ')] 

結果,例如,使用您的數據:

[[3, 1], [5, 4, 0], [8, 3, 4]] 
相關問題