我所有的文本文件格式如下所示,我将其引入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 :(得分:1)
您可以通过以下方式执行此操作:
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
说明:
答案 1 :(得分:1)
func testExample() {
let app = XCUIApplication()
let textField = app.otherElements.containing(.navigationBar, identifier:"id").children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .textField).element
textField.tap()
textField.tap()
app.navigationBars["id"].buttons["Done"].tap()
}
答案 2 :(得分:1)
怎么样:
items = {}
with open("temp.txt") as f:
for line in f:
item,cost = line.split('#')
cost = float(cost)
items[item] = cost
现在,你有一个字典,按项目键入#34;名称&#34; (所以它们需要在你的文件中是唯一的,否则字典不是这里最好的结构),每个值都是一个与解析成本相对应的浮点数。
# 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
您可能需要查看一些极端情况,以使此解决方案更加强大。例如,如果项目&#34; name&#34;包括一个#符号(即每行有多个#),这些值没有经过适当的格式化以便由float
等进行解析。
答案 3 :(得分:0)
您可以使用:
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))
Total Price
$65.5
Number of tools
3
我们必须cast
价格(line.split("#")[1]
)(string
)到float
,否则我们会获得{ {1}}当我们尝试将Type Error
改为add
。
total_price
答案 4 :(得分:0)
由于我应该刷新我的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
转换为浮点值):
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
但是除了编码乐趣之外,我建议您尝试获取干净的类似csv的数据并通过csv
类正确处理。