Python:从文本中拆分数字,然后求和

Python:从文本中拆分数字,然后求和,python,Python,我所有的内容都是一个文本文件,格式如下,我将其引入Python: hammer#9.95 saw#20.15 shovel#35.40 最后,我想开发一个动态查询,允许我删除“#”符号并替换为“$”符号,然后在文本文件中添加值/计算其中的项数。我通过一些尝试和错误得出了这个结论,但处理文本文件中的更改并不是动态的: # display header line for items list print('{0: <10}'.format('Item'), '{0:

我所有的内容都是一个文本文件,格式如下,我将其引入Python:

    hammer#9.95
    saw#20.15
    shovel#35.40
最后,我想开发一个动态查询,允许我删除“#”符号并替换为“$”符号,然后在文本文件中添加值/计算其中的项数。我通过一些尝试和错误得出了这个结论,但处理文本文件中的更改并不是动态的:

 # display header line for items list
print('{0: <10}'.format('Item'), '{0: >17}'.format('Cost'), sep = '' )

# add your remaining code below
with open('invoice.txt','rt') as infile:
    for line in infile:
        print("{:<21} {}".format(line.strip().split('#')[0],"$"+line.strip().split("#")[1]))

print(' ')
str1 = 'Total cost\t' +'      ' + '$65.50'
print(str1)

str2 = 'Number of tools\t' + '           ' +'3'
print(str2)
#显示项目列表的标题行
打印(“{0:17}”。格式('Cost'),sep=”)
#在下面添加剩余的代码
以open('invoice.txt','rt')作为填充:
对于填充中的线:

打印(“{:您可以通过以下方式执行:

d = ['hammer#9.95', 'saw#20.15', 'shovel#35.40']

## replace hash
values = []
items = set()
for line in d:
    line = line.replace('#', '$')
    values.append(line.split('$')[1])
    items.add(line.split('$')[0])

## sum values
sum(map(lambda x: float(x), values)) 
65.5

## count items
len(items)
3
说明:

  • 要计数项目,我们使用了一个集合来获取唯一计数。如果您想要全部,请使用列表
  • 我们通过按美元符号拆分从列表中提取数字来计算总和
  • 您可以使用:

    total_price, total_products = 0, 0
    for line in [open('invoice.txt').read().split("\n")]: 
        total_price += float(line.split("#")[1]); total_products += 1
    print("Total Price\n${}".format(total_price))
    print("Number of tools\n{}".format(total_products))
    


    我们必须
    价格
    line.split(“#”)[1]
    )转换为
    浮点数
    ,否则当我们尝试
    将其添加到
    总价中时,会出现
    类型错误

    float(line.split("#")[1])
    
    那么:

    items = {}
    with open("temp.txt") as f:
        for line in f:
            item,cost = line.split('#')
            cost = float(cost)
            items[item] = cost
    
    现在,您有了一个字典,由项“name”键入(因此它们在您的文件中必须是唯一的,否则字典在这里不是最好的结构),每个值都是对应于解析成本的浮点值

    # Print items and cost
    print(items.items())
    #> dict_items([('hammer', 9.95), ('saw', 20.15), ('shovel', 35.4)])
    
    # Print Number of Items
    print(len(items))
    #> 3
    
    # Print Total Cost (unformatted)
    print(sum(items.values()))
    #> 65.5
    
    # Print Total Cost (formatted)
    print("$%.02f" % sum(items.values()))
    #> $65.50
    

    为了使此解决方案更加健壮,您可能需要考虑一些特殊情况。例如,如果项目“名称”包含一个#符号(即每行有多个#),值的格式不正确,无法由
    float
    等进行解析。

    由于我应该刷新Python技能的时间已经很长了,所以我对您的问题很感兴趣,并提出了一个解析器类:

    import re
    from contextlib import contextmanager
    
    
    class Parser(object):
    
        def __init__(self, file_path, regex):
            self.file_path = file_path
            self.pattern = re.compile(regex, flags=re.LOCALE | re.IGNORECASE | re.UNICODE)
            self.values = []
            self.parse()
    
        @contextmanager
        def read_lines(self):
            try:
                with open(self.file_path, "r", encoding="utf-8") as f:
                    yield f.readlines()
            except FileNotFoundError:
                print("Couldn't open file: ", self.file_path)
    
        def parse_line(self, line):
            try:
                return self.pattern.match(line).groupdict()
            except AttributeError:
                return None
    
        def parse(self):
            with self.read_lines() as lines:
                self.values = [value for value in map(self.parse_line, lines) if value]
    
        def get_values(self, converters=dict()):
            if len(converters) is 0:
                return self.values
            new_values = []
            for value in self.values:
                new_value = {}
                for key in value:
                    if key in converters:
                        new_value[key] = converters[key](value[key])
                    else:
                        new_value[key] = value[key]
                new_values.append(new_value)
            return new_values
    
    此类采用一个文件路径和一个类似正则表达式的字符串,然后将其编译为一个正则表达式对象。实例化时,它读取并解析文件内容,同时忽略无效行(与正则表达式语法不匹配,如空行)

    我还添加了一个
    get_values
    方法,可以将转换器应用于正则表达式中的命名组,参见示例(它将每行的命名组
    price
    转换为浮点值):

    但除了编码乐趣,我建议您尝试获取干净的类似csv的数据,并通过
    csv
    类正确处理它。

    有关“动态性”,请参阅正则表达式:
    # Print items and cost
    print(items.items())
    #> dict_items([('hammer', 9.95), ('saw', 20.15), ('shovel', 35.4)])
    
    # Print Number of Items
    print(len(items))
    #> 3
    
    # Print Total Cost (unformatted)
    print(sum(items.values()))
    #> 65.5
    
    # Print Total Cost (formatted)
    print("$%.02f" % sum(items.values()))
    #> $65.50
    
    import re
    from contextlib import contextmanager
    
    
    class Parser(object):
    
        def __init__(self, file_path, regex):
            self.file_path = file_path
            self.pattern = re.compile(regex, flags=re.LOCALE | re.IGNORECASE | re.UNICODE)
            self.values = []
            self.parse()
    
        @contextmanager
        def read_lines(self):
            try:
                with open(self.file_path, "r", encoding="utf-8") as f:
                    yield f.readlines()
            except FileNotFoundError:
                print("Couldn't open file: ", self.file_path)
    
        def parse_line(self, line):
            try:
                return self.pattern.match(line).groupdict()
            except AttributeError:
                return None
    
        def parse(self):
            with self.read_lines() as lines:
                self.values = [value for value in map(self.parse_line, lines) if value]
    
        def get_values(self, converters=dict()):
            if len(converters) is 0:
                return self.values
            new_values = []
            for value in self.values:
                new_value = {}
                for key in value:
                    if key in converters:
                        new_value[key] = converters[key](value[key])
                    else:
                        new_value[key] = value[key]
                new_values.append(new_value)
            return new_values
    
    parser = Parser(r"fully_qualified_file_path.txt", r".\s*(?P<name>[\w\s]+)\#(?P<price>[\d\.]+)")
    
    total = 0
    count = 0
    for line in parser.get_values({'price': lambda x: float(x)}):
        total += line['price']
        count += 1
        print('Item: {name}, Price: ${price}'.format(**line))
    
    print()
    print('Item count:', count)
    print('Total:', "${0}".format(total))
    
    Item: hammer, Price: $9.95
    Item: saw, Price: $20.15
    Item: shovel, Price: $35.4
    
    Item count: 3
    Total: $65.5