完整的新手在這里,請幫助。假設我有一個如下所示的文本檔案:
some strings
go here
* head1 head2 head3 ... headN
3 "a" 0.3 ... -2
0.1 "b" 5 ... 1
10 "c" -4 ... 100
# and other rows with some numbers
所以,我在感興趣的主要塊之前有幾個字串。這個塊有“標題”行,注意它以“*”開頭,真正的列的標題從第 2 列開始。接下來是帶有一些數字和字串的行,它們對應于特定的 head[i]。
我需要根據 head2 列中的字串值逐行處理此塊:例如,如果 head2 的值為“a”,則在檔案中寫入新字串,如“param1 = 3,param2 = 0.3”,即取處理的當前行的 head1 和 head3 中的值。
問題是這個“標題”行可以有不同數量的元素,并且 head[i] 的順序可以變化,所以這一行可以是
* head3 head1 head2 ... headN
我需要在列名和列值之間建立一些關聯,以便我可以使用每一行,例如 if line.head2 == "a" then ... 怎么做?
uj5u.com熱心網友回復:
您可以使用 DictReader,它將為您提供 csv 模塊的所有功能和穩健性,但您必須首先跳過初始行。
您可以使用 3 步處理:
- 忽略以 a 開頭的行之前的任何行
* *在跳過其初始字符后從該行中提取欄位名稱- 將其他行作為您知道欄位名稱的普通 csv 檔案處理
可能的代碼:
with open(filename) as fd:
# skip the initial lines up to a line starting with a *
for line in fd:
if line.startswith('*'):
break
# use a DictReader to parse that line (after the initial *)
rd = csv.DictReader(io.StringIO(line[1:]), delimiter=' ',
skipinitialspace=True)
# prepare a DictReader for the rest of the file
fieldnames = rd.fieldnames
rd = csv.DictReader(fd, fieldnames=fieldnames, delimiter=' ',
skipinitialspace=True)
for row in rd:
if row['head2'] == 'a':
# add your processing here...
使用 csv 模塊的基本原理是 Python 自帶電池,并且 csv 模塊是一個非常強大的模塊,能夠處理包含換行符分隔符的欄位。因此,最佳實踐建議始終使用它來處理 csv 檔案而不是自定義決議器。
uj5u.com熱心網友回復:
這將逐行讀取您的文本檔案,如果找到標題行,則將當前行作為字典寫入名為rows.
我添加了一個簡單示例,說明如何rows訪問串列中的元素。
headers = []
rows = []
with open('input.txt') as f:
for line in f:
split_line = line.strip().split()
if headers:
rows.append(dict(zip(headers, split_line)))
if split_line and '*' == split_line[0]:
headers = split_line[1:]
for row in rows:
if row['head2'] == '"a"':
print('found an "a"')
檔案:輸入.txt
some strings
go here
* head1 head2 head3 headN
3 "a" 0.3 -2
0.1 "b" 5 1
10 "c" -4 100
uj5u.com熱心網友回復:
如果它總是以 3 行開頭,您可以使用 python 的陣列跳過行 [3:]。如果您逐行閱讀此文本,請使用 . 等待“*” if line[0] == '*'。
現在對于決議部分,首先我們將使用 split 函式決議標頭
headers = line.split()[1:]
我們通過空格分隔符進行拆分(默認為拆分功能),然后我們忽略拆分中的第一個元素(“*”),這將為您提供一個標題陣列。
現在我們可以繼續決議每一行并在標題和值之間創建映射(我忽略了從 str 到 int/float/任何其他型別的值決議)
data_dict = {}
splitted_line = line.split()
for i in range(len(headers)):
data_dict[headers[i]] = splitted_line[i]
print(data_dict)
parsed_data.append(data_dict)
而 parsed_data 是全域資料容器
uj5u.com熱心網友回復:
這個答案只是@ SergeBallesta的答案的微小“改進” (之前發布在這個評論中)。
要在手動出現星號之前不迭代檔案,我們可以使用itertools.dropwhile().
dropwhile(lambda x: not x.startswith("*"), f)
它將跳過所有行,直到"*"出現從開始的行。
為了不重新初始化DictReader兩次以洗掉第一列,我們可以修補DictReader.fieldnames從DictReader初始化后讀取的第一行獲得的內容。從串列中洗掉第一項可以通過簡單的del陳述句來完成。
所以這是我的版本:
from csv import DictReader
from itertools import dropwhile
with open("file.txt") as f:
reader = DictReader(dropwhile(lambda x: not x.startswith("*"), f),
delimiter=' ', skipinitialspace=True)
del reader.fieldnames[0]
for row in reader:
if row["head2"] == "a":
# do something
你可以幫助我的國家,查看我的個人資料資訊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/526541.html
標籤:Python细绳
