比较日期和打印总和

时间:2016-01-04 23:20:44

标签: python file

我的程序必须比较当天/日期的日期和打印总和。 日期将始终按升序排列。

文件:

09/12/2015|9380.0
09/12/2015|7667.0
10/12/2015|3190.0
14/12/2015|3190.0
14/12/2015|5940.0

结果:

09/12/2015 -> 17047.0
10/12/2015 -> 3190.0
14/12/2015 -> 9130.0

这是我的程序

start = "09/12/2015"
end = "14/12/2015"

startstart = datetime.strptime(start, "%d/%m/%Y")
endend   = datetime.strptime(end,"%d/%m/%Y")

with open("fileName.txt", "r") as report:
    allData = csv.reader(report, delimiter = "|")

    for line in allData:
        dataLine = datetime.strptime(line[0], "%d/%m/%Y")
        if dataLine >= startstart and dataLine <= endend :
            print("{0} -> {1}|".format(line[0], line[1]))

我的结果现在有了这个程序:

09/12/2015 -> 9380.0
09/12/2015 -> 7667.0
10/12/2015 -> 3190.0
14/12/2015 -> 3190.0
14/12/2015 -> 5940.0

问题是我打印每个日期和价格,我需要为该日期制作一个日期和所有价格的总和。

5 个答案:

答案 0 :(得分:1)

import csv
from datetime import strptime
from itertools import groupby

# this could also be written as
#   get_day = lambda row: row[0]
# or as
#   from operator import itemgetter    # thanks to @ShadowRanger!
#   get_day = itemgetter(0)
def get_day(row):
    return row[0]

def get_date(s):
    return strptime(s, "%d/%m/%Y")

start = get_date("09/12/2015")
end   = get_date("14/12/2015")

with open("filename.csv", newline='') as inf:
    rows = csv.reader(inf, delimiter='|')
    for day, day_rows in groupby(rows, get_day):
        if start <= get_date(day) <= end:
            day_total = sum(float(v) for d,v in day_rows)
            print("{} -> {}".format(day, day_total))

(在给定的输入上)产生

09/12/2015 -> 17047.0
10/12/2015 -> 3190.0
14/12/2015 -> 9130.0

根据需要。

编辑: lambda是一种创建无名函数的方法,它返回单个值; fn = lambda x: x[0]

完全相同
def fn(x):
    return x[0]

我把它重写为一个单独的函数而不是lambda ;-)希望有所帮助。

此示例中的

Edit2: groupby需要

[
    ('09/12/2015', '9380.0'),
    ('09/12/2015', '7667.0'),
    ('10/12/2015', '3190.0'),
    ('14/12/2015', '3190.0'),
    ('14/12/2015', '5940.0')
]

并将其转换为

[
    ('09/12/2015', [('09/12/2015', '9380.0'), ('09/12/2015', '7667.0')]),
    ('10/12/2015', [('10/12/2015', '3190.0'),]),
    ('14/12/2015', [('14/12/2015', '3190.0'), ('14/12/2015', '5940.0')])
]

(即每天的子列表)。然后,您可以轻松获取每日小计(这是day_total = sum(...)行正在执行的操作)。

编辑3:我已在开始日期和结束日期检查中添加。

答案 1 :(得分:1)

我建议使用collections.defaultdict()对数字求和,然后使用sorted()保持以下顺序:

from datetime import datetime
from collections import defaultdict

start = "09/12/2015"
end = "14/12/2015"

start = datetime.strptime(start, "%d/%m/%Y")
end = datetime.strptime(end, "%d/%m/%Y")

d = defaultdict(float)

with open('file') as f:
    l = [i.split('|') for i in f.read().splitlines()]

for key, value in l:
    d[key] += float(value)

l = sorted(((key, value) for (key, value) in d.items()
            if datetime.strptime(key, "%d/%m/%Y") >= start and
            datetime.strptime(key, "%d/%m/%Y") <= end),
           key=lambda x: datetime.strptime(x[0], "%d/%m/%Y"))

for key, value in l:
    print('{} -> {}'.format(key, value))

但是,由于您希望保持订单,我还建议您使用collections.OrderedDict()。这是另一个例子,可能比上面的更简单:

from datetime import datetime
from collections import OrderedDict
start = "09/12/2015"
end = "14/12/2015"

start = datetime.strptime(start, "%d/%m/%Y")
end = datetime.strptime(end, "%d/%m/%Y")

with open('file') as f:
    l = [i.split('|') for i in f.read().splitlines()]

d = OrderedDict()

for key, value in l:
    date = datetime.strptime(key, "%d/%m/%Y")
    if date >= start and date <= end:
        try:
            d[key] += float(value)
        except KeyError:
            d[key] = float(value)

for key, value in d.items():
    print('{} -> {}'.format(key, value))

演示:

09/12/2015 -> 17047.0
10/12/2015 -> 3190.0
14/12/2015 -> 9130.0

答案 2 :(得分:1)

您不需要转换为日期时间,只需使用OrderedDict进行分组和求和:

from collections import OrderedDict
import csv
with open("in.csv") as f:
    od = OrderedDict()
    # dte = date string, f = number
    for dte, f in csv.reader(f,delimiter="|"):
        # cast to float
        f = float(f)
        # if we have not seen the key before,
        #  it will get added  with default value of 0
        od.setdefault(dte, 0)
        # access by key/date and add to value
        od[dte] += f

for t in od.items():
    print("{} ---> {}".format(*t))

输出:

09/12/2015 ---> 17047.0
10/12/2015 ---> 3190.0
14/12/2015 ---> 9130.0

如果您想查找特定日期,可以使用日期字符串进行访问。

print(od[start])
17047.0

答案 3 :(得分:0)

只需将数据读入列表,最终看起来像这样:

data = [[date_1, price_1], [date_2, price_2], ..., [date_n, price_n]]

然后使用这段代码:

from operator import itemgetter

prices = {}
for entry in data:
    try:
        prices[entry[0]] += entry[1]
    except KeyError:
        prices[entry[0]] = entry[1]

sorted_prices = sorted(prices.items(), key=itemgetter(0))

我还没有对此进行测试,但这是正确的想法。根据您使用的数据量,您可能希望使用一种解决方案来保持数据的分类。这需要大量数据。在这种情况下,您可以使用OrderedDict库中的collections

答案 4 :(得分:0)

我发现使用dict来积累价格更容易理解,但是你可能不同意:

import csv
from datetime import datetime

#read in data
with open('filename.csv', 'r') as report:
    alldata = [row for row in
               csv.reader(report, delimiter = "|")]

#define a dict to store each date (as key) and price (as value)
datePrice = {}

#use dict.get function to accumulate price
for row in alldata:
    dateKey = datetime.strptime(row[0], "%d/%m/%Y")
    datePrice[dateKey] =  datePrice.get(dateKey, 0) + float(row[1])

#make a sorted list of keys and iterate through the list
for date in sorted(datePrice):
    print("{0} -> {1}".format(datetime.strftime(date, "%d/%m/%Y")
                              , datePrice[date]))

这是输出:

>09/12/2015 -> 17047.0
>10/12/2015 -> 3190.0
>14/12/2015 -> 9130.0