2017-07-25 25 views
1

在SO上也有類似的問題,但沒有涉及我需要的細節。使用csv閱讀器從列表中刪除行並列出python

我有以下代碼,試圖根據指定的用戶輸入刪除文件中的一行。該方法是

  1. 讀取文件到列表
  2. 刪除列表中的相關行(理想情況下,而列表中的閱讀?)
  3. 過寫文件。

對於最好的解決方案(對於初學者,用於教學/學習目的),我希望得到一些指導和評論,以便在csv中執行這種簡單的Python刪除/編輯操作讀者。

代碼

""" ==============TASK 
1. Search for any given username 
2. Delete the whole row for that particular user 

e.g. 
Enter username: marvR 
>>The record for marvR has been deleted from file. 
""" 

import csv 

#1. This code snippet asks the user for a username and deletes the user's record from file. 

updatedlist=[] 
with open("fakefacebook.txt",newline="") as f: 
    reader=csv.reader(f) 
    username=input("Enter the username of the user you wish to remove from file:") 
    for row in reader: #for every row in the file 
     if username not in updatedlist: 
     updatedlist=row #add each row, line by line, into a list called 'udpatedlist' 
     print(updatedlist) 

#delete the row for the user from the list? 
#overwrite the current file with the updated list? 

文件內容:

username,password,email,no_of_likes 
marvR,pass123,[email protected],400 
smithC,open123,[email protected],200 
blogsJ,2bg123,[email protected],99 

更新

基於下面的答案,我有這個,但是當它覆蓋文件,它不會正確更新列表,不知道爲什麼。

import csv 
def main(): 
    #1. This code snippet asks the user for a username and deletes the user's record from file. 
    updatedlist=[] 
    with open("fakefacebook.txt",newline="") as f: 
     reader=csv.reader(f) 
     username=input("Enter the username of the user you wish to remove from file:") 
     for row in reader: #for every row in the file 
      if row[0]!=username: #as long as the username is not in the row ....... 
      updatedlist=row #add each row, line by line, into a list called 'udpatedlist' 
      print(updatedlist) 
    updatefile(updatedlist) 

def updatefile(updatedlist): 
    with open("fakefacebook.txt","w",newline="") as f: 
     Writer=csv.writer(f) 
     Writer.writerow(updatedlist) 
     print("File has been updated") 


main() 

它似乎正確地打印更新文件(作爲列表),因爲它刪除了輸入的用戶名。但是在寫入文件時,它只會向文件打印一個用戶名。

有什麼想法,我可以接受最終答案?

回答

2

if username not in updatedlist:

對我來說應該是:

if row[0] != username:

然後在第二循環中,您寫updatedlist到CSV文件。 我會在閱讀的時候將所有內容都寫在另一個文件中,然後最後刪除舊文件並將其替換爲新文件,這使得它只有一個循環。

編輯:

updatedlist=rowupdatedlist.append(row)替換:第一個裝置重寫updatedlist與一個行,而第二個裝置增加一個行到它。

writerow寫入一行,然後給它一個行列表。 改爲使用writerows,您的寫作功能將起作用。

你幾乎完成了這一切,這是我的目標。 其他一些答案已經給你更好的(更快,更乾淨...)的方式,所以我不會。

+0

最簡單的答案 - 輝煌的感謝!如果行[0]!=用戶名:工作。你還可以添加你的答案,包括最有效/簡單的方式,然後寫入文件(你的覆蓋建議?) – MissComputing

+0

如果你能看到我的更新的問題 - 並回答它,我可以接受你的答案,因爲我已經使用了一半。謝謝 – MissComputing

+0

編輯,希望它有幫助。 –

1

這樣的事情應該可以做到,使用csv模塊。由於您已將表格數據與定義的列結構化在一起,因此您應該使用DictReaderDictWriter來讀寫您的文件;

import csv 

with open('fakefacebook.txt', 'r+') as f: 
    username = input("Enter the username of the user you wish " 
         "to remove from file:") 
    columns = ['username', 'password', 'email', 'no_of_likes'] 

    reader = csv.DictReader(f, columns) 
    filtered_output = [line for line in reader if line['username'] != username] 

    f.seek(0) 
    writer = csv.DictWriter(f, columns) 
    writer.writerows(filtered_output) 
    f.truncate() 

這將打開輸入文件,過濾出其中的用戶名是等於所需的用戶名要刪除任何條目,並寫入留下哪些條目背出輸入文件,覆蓋什麼已經存在。

+0

DictReader - 將閱讀更多內容。謝謝! – MissComputing

1

我推薦這種方法:

with open("fakefacebook.txt", 'r+') as f: 
    lines = f.readlines() 
    f.seek(0) 

    username = input("Enter the username of the user you wish to remove from file: ") 
    for line in lines: 
     if not username in line.split(',')[0]: # e.g. is username == 'marvR', the line containing 'marvR' will not be written 
      f.write(line) 

    f.truncate() 

所有的文件中的行被讀入lines。然後我回到f.seek(0)的文件起始位置。此時,用戶會被要求輸入一個用戶名,然後在回寫該文件之前用它來檢查每一行。如果該行包含指定的用戶名,則不會寫入,因此會「刪除」該用戶名。最後我們用f.truncate()刪除任何多餘部分。我希望這有助於,如果你有任何問題不要猶豫,問!

+0

如果有人使用''marvR''作爲密碼怎麼辦?他們應該被刪除嗎? :( –

+0

謝謝flevinkelming - 你能看到我的更新,並建議最終的解決方案 - 我快到了。 – MissComputing

+1

@MissComputing你的行'updatedlist = row'應該是'updatedlist.append(row)' - 你目前寫的,不包含'username'的最後一行被分配給'updatedlist',並且該行是你當前正在寫入的文件,而不是** all **行不包含用戶名。 – flevinkelming

1

我試着堅持你的代碼:(編輯:不優雅,但是儘可能接近到OPS代碼)

""" ==============TASK 
1. Search for any given username 
2. Delete the whole row for that particular user 

e.g. 
Enter username: marvR 
>>The record for marvR has been deleted from file. 
""" 

import csv 

#1. This code snippet asks the user for a username and deletes the user's record from file. 

updatedlist=[] 
with open("fakefacebook.txt",newline="") as f: 
    reader=csv.reader(f) 
    username=input("Enter the username of the user you wish to remove from file:") 
    content = [] 
    for row in reader: #for every row in the file 
    content.append(row) 

# transpose list 
content = list(map(list, zip(*content))) 
print(content) 
index = [i for i,x in enumerate(content[0]) if x == username] 
for sublist in content: 
    sublist.pop(index[0]) 

print(content) 

# transpose list 
content = list(map(list, zip(*content))) 

#write back 
thefile = open('fakefacebook.txt', 'w') 
for item in content: 
    thefile.write("%s\n" % item) 

不過,我會建議使用numpy的還是熊貓

+0

這是非常有用的 - 但似乎這麼長,我想沒有上述的numpy或pandas它會很長嗎? – MissComputing

+1

我很困惑,爲什麼需要列表的轉置? –

+0

@TomWyllie我只是試圖解決OPs代碼的教育原因。可以從頭開始寫更簡單的東西,但它會對你有什麼幫助?如果你運行代碼,你會發現OP加載列表的方式使得它變得醜陋,所以我需要將索引轉置爲找出名字的索引。 – BrutalGames

1

而對於另一個答案:寫入一個新文件,然後重命名它!

import csv 
import os 

def main(): 
    username = input("Enter the username of the user you wish to remove from file:") 
    # check it's not 'username'! 

    #1. This code snippet asks the user for a username and deletes the user's record from file. 
    with open("fakefacebook.txt", newline="") as f_in, \ 
      open("fakefacebook.txt.new", "w", newline="") as f_out: 
     reader = csv.reader(f_in) 
     writer = csv.writer(f_out) 
     for row in reader: #for every row in the file 
      if row[0] != username: # as long as the username is not in the row 
       writer.writerow(row) 
    # rename new file 
    os.rename("fakefacebook.txt.new", "fakefacebook.txt") 

main() 
+0

的問題。我完全試過你的代碼,只要用戶名不在行中,就會出現行[0]!= username:# IndexError:列表索引超出範圍...但它有點repl.it - https://repl.it/Jhcm/2任何想法?爲什麼它在IDLE上列出索引超出範圍!? repl.it – MissComputing

+0

上的另一個錯誤repl.it(os沒有定義)的錯誤是因爲'import os'不存在。在IDLE中,文件末尾是否有空行? –

+0

不完全確定我做了什麼 - 但它現在有效! https://repl.it/Jhcm/7(在repl.it和IDLE上)謝謝 – MissComputing