【问题标题】:Python extract data and create dataPython 提取数据和创建数据
【发布时间】:2021-06-13 23:07:47
【问题描述】:

我有一个 100GB 数据的 txt 文件... txt 文件示例:

(1, 'Dog', '', '3', 'Brown','Female,)
(2, 'Primate', 'Orangutan', '10', 'Orange','Male,)

我想作为输出:

List number: 1               Age: 3
Type: Dog                    Hair Color: Brown
Race: None                   Sex: Female
-------------------------------------------------------
List number: 2               Age: 10
Type: Primate                Hair Color: Orange
Race: Orangutan              Sex: Male

如何在 python 上实现这一点??? 谢谢你,我真的很感激你的帮助!!

【问题讨论】:

  • 可以分享部分txt文件吗?值是否用逗号 (CSV) 分隔?
  • 是一行还是多行?您能否在谷歌驱动器中分享文件样本或将样本附加到您的问题中?
  • 该死的 100GB 纯文本。 Jees 测验,将其上传到谷歌驱动器@Maze 需要很长时间
  • 有人回答了您的问题,但我认为它不会起作用,因为您将数据保存在 txt 文件中,并且它将整行读取为输入字符串,这将需要一些预处理。不管怎样,你已经接受了答案。
  • 也许您想解释将1e+9 行文本(或多或少)转换为4e+9 行输出的目的。我想它既不节省空间也不读取输出。但目的可能有助于回答您的问题。

标签: python python-3.x database list


【解决方案1】:

您可以使用str.ljust() 获取第一项之后的空格。

data = [
    (1, 'Dog', '', '3', 'Brown', 'Female'),
    (2, 'Primate', 'Orangutan', '10', 'Orange', 'Male')
]


first = True
for i, type_, race, age, hair_color, sex in data:
    if not first:
        print("-" * 80)
    else:
        first = False
    print(f"List number: {str(i).ljust(30)}Age: {age or None}")
    print(f"Type: {str(type_ or None).ljust(37)}Hair Color: {hair_color or None}")
    print(f"Race: {str(race or None).ljust(37)}Sex: {sex or None}")

输出

List number: 1                             Age: 3
Type: Dog                                  Hair Color: Brown
Race: None                                 Sex: Female
--------------------------------------------------------------------------------
List number: 2                             Age: 10
Type: Primate                              Hair Color: Orange
Race: Orangutan                            Sex: Male

为什么是 30 和 37?
30 是一个随机值。
37 = 30 + (len("List number: ") - len("Type: "))"Race: " 相同)。

【讨论】:

  • 谢谢你 Sven Eberth !!!.... 我真的很感激 :) ...
【解决方案2】:

我认为你可以先创建一个带有输出模板的字符串,然后用像这样的格式函数填充它:

data = [
    (1, 'Dog', '', '3', 'Brown', 'Female'),
    (2, 'Primate', 'Orangutan', '10', 'Orange', 'Male')
]

template = """List number: {0:<23} Age: {3:<10}
Type: {1:<30} Hair Color: {4:<30}
Race: {2:<30} Sex: {5:<30}
"""

for idx, _ in enumerate(data):
    print('-'*70) if idx > 0 else None
    print(template.format(*_))

使用上下文管理器:

with open(filename) as file:
    for line in file:
        data = split_line_to_list(line)
        print('-'*70)
        print(template.format(*data))

【讨论】:

  • 谢谢安迪·巴甫洛夫 !!!.... 我真的很感激 :) ...
  • '''with open('1.txt', 'r') as f:''' 嘿,安迪,我如何使用您的代码从 txt 文件中的每一行打开它??
  • 是的。使用上下文管理器。我为我的回复写了额外的代码,
【解决方案3】:

我使用了@AndyPavlov生成的模板

import sys
import re

__Animal_attributes__ = {
    'id': int,
    'type': str,
    'race': str,
    'age': int,
    'hair_color': str,
    'sex': str
}

class TxtFileHandler:
    @staticmethod
    def parse(data):
        if len(data.strip()) > 0:
            return [a.strip() for a in re.sub(re.compile(r'[\(\)\r\n\']'), '', data).split(',')]
        else:
            raise Exception(f'Error parsing data [{data}]')

    @staticmethod
    def read(filename:str, fn, data: list = list()):
        try:
            file = open(filename, 'r')
        except OSError as e:
            print(e)
        with file:
            for line in file:
                try:
                    data.append(fn(line))
                except Exception as e:
                    print(f'Error executing callback [{fn}] with data [{line}]. Received exception: {e}')
            return data

class Animal:
    def __init__(self, *args):
        for idx, (attribute, parsing_fn) in enumerate(__Animal_attributes__.items()):
            setattr(self, attribute, parsing_fn(args[idx]))

    def __str__(self) -> str:
        template = """List number: {0:<23} Age: {3:<10}
Type: {1:<30} Hair Color: {4:<30}
Race: {2:<30} Sex: {5:<30}"""
        return template.format(*[getattr(animal, a) for a in __Animal_attributes__.keys()])

if __name__ == '__main__':
    filename = sys.argv[1]
    animals = TxtFileHandler.read(filename, lambda line: Animal(*TxtFileHandler.parse(line)))
    for idx, animal in enumerate(animals):
        print(animal, f'\n{"-"*70 if idx < len(animals)-1 else ""}')

【讨论】:

  • 谢谢 loko !!!.... 我真的很感激 :) ... 文件名是 '1.txt' .... 但每次我运行代码时它都会显示:data = sys.argv[1] IndexError: 列表索引超出范围
  • 哦,运行脚本的时候还要加上参数。例如python animals.py ./data/animals.
  • 非常感谢 loko :) .... 对我来说,它可以在第 32 行中输入:data = '1.txt' .... 而不是 data = sys.argv[1 ] .........非常感谢你,我真的很感激! :)
  • 我很高兴它对你有用。我修复了处理空行的代码,以防万一。不过,可以通过更改函数对象的 lambda 来提高可读性。
猜你喜欢
  • 1970-01-01
  • 2019-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-20
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
相关资源
最近更新 更多