按特定顺序从 .txt 中读取项目

Reading items from .txt in specific order

我正在尝试从包含以下内容的 .txt 文件中读取项目:

294.nii.gz [[9, 46, 54], [36, 48, 44], [24, 19, 46], [15, 0, 22]]
296.nii.gz [[10, 13, 62], [40, 1, 64], [34, 0, 49], [27, 0, 49]]
312.nii.gz [[0, 27, 57], [25, 25, 63], [0, 42, 38], [0, 11, 21]]

我想提取数据的方式是:

  1. 获取物品名称:294.nii.gz
  2. 项目坐标连续:[9, 46, 54] [36, 48, 44] ...
  3. 获取下一项:

N.B。所有项目都具有相同数量的 3D 坐标。

到目前为止,我可以通过以下代码读取数据:

coortxt = os.path.join(coordir, 'coor_downsampled.txt')
with open(coortxt) as f:
    content = f.readlines()
content = [x.strip() for x in content]

for item in content:
    print(item.split(' ')[0])

这只打印项目名称:

294.nii.gz
296.nii.gz
312.nii.gz

如何以我需要的格式获取其余数据?

因此,您完成了将列表的字符串表示形式转换为列表的有趣任务。

为此,您可以使用 ast library. Specifically, the ast.literal_eval 方法。

免责声明:

根据文档:

Warning It is possible to crash the Python interpreter with a sufficiently large/complex string due to stack depth limitations in Python’s AST compiler.

这与使用 eval 不同。来自 docs:

Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

This can be used for safely evaluating strings containing Python expressions from untrusted sources without the need to parse the values oneself.

你得到数据的第一部分item.split(' ')[0]

然后,您将使用 item.split(' ')[1:] 获取(例如)内容为 "[[9, 46, 54], [36, 48, 44], [24, 19, 46], [15, 0, 22]]".

的字符串

如果这是您愿意接受的风险:

使用ast的演示:

import ast
list_str = "[[9, 46, 54], [36, 48, 44], [24, 19, 46], [15, 0, 22]]"
list_list = ast.literal_eval(list_str)
print(isinstance(list_list, list))
#Outputs True
print(list_list)
#Outputs [[9, 46, 54], [36, 48, 44], [24, 19, 46], [15, 0, 22]]

将它与您的代码结合在一起:

import os 
import ast

coortxt = os.path.join(coordir, 'coor_downsampled.txt')
with open(coortxt) as f:
    content = f.readlines()
content = [x.strip() for x in content]

for item in content:
    name,coords_str = item.split(' ')[0], item.split(' ')[1:]
    coords = ast.literal_eval(coords_str)
    #name,coords now contain your required data
    #use as needed


相关帖子:

How to convert string representation of list to a list?

其他人建议在 Python 中使用动态求值器 eval(甚至 ast.literal_eval,这确实有效,但仍然有一些方法可以在没有它的情况下执行这种解析.

鉴于 coor_downsampled.txt 文件中坐标列表的格式非常 json-esque,我们可以使用非常酷的 json 模块来解析它。

注意:

有消息称 json.loads is 4x faster than eval, and almost 7x faster than ast.literal_eval,这取决于您是否需要速度,我建议您使用更快的选项。

完整示例

import os
import json

coortxt = 'coor_downsampled.txt'
with open(coortxt) as f:
    content = f.readlines()
content = [x.strip() for x in content]

for item in content:
    # split the line just like you did in your own example
    split_line = item.split(" ")

    # the "name" is the first element
    name = split_line[0]

    # here's the tricky part.
    coords = json.loads("".join(split_line[1:]))
    print(name)
    print(coords)

说明

让我们分解一下这条棘手的线coords = json.loads("".join(split_line[1:]))

split_line[1:] 会给你第一个 space 之后的所有内容,所以像这样:

['[[9,', '46,', '54],', '[36,', '48,', '44],', '[24,', '19,', '46],', '[15,', '0,', '22]]']

但是用"".join()包裹它,我们可以把它变成

'[[9,46,54],[36,48,44],[24,19,46],[15,0,22]]' 改为字符串。

一旦我们有了它,我们只需json.loads()来获取实际的列表对象

[[9, 46, 54], [36, 48, 44], [24, 19, 46], [15, 0, 22]].