【问题标题】:Iterate over . csv file --> write into two dictionaries迭代。 csv 文件 --> 写入两个字典
【发布时间】:2016-07-21 12:58:46
【问题描述】:

csv 看起来像这样:

2016-04-01 02:17    16.7    51.9
2016-04-01 02:18    16.7    51.9
2016-04-01 02:19    16.6    52.0
2016-04-01 02:20    16.6    52.2
2016-04-01 02:21    16.7    52.2
2016-04-01 02:22    16.7    52.1
2016-04-01 02:23    16.6    52.2
2016-04-01 02:24    16.6    52.2
2016-04-01 02:25    16.6    52.2

文件每分钟记录一次传感器的温度和湿度。每个测量都是cvsfile 中的一行。

我想遍历这个文件并添加行,具体取决于字典的时间。 所以一个字典应该保存从nownow - 24hours的所有行,另一个字典应该保存从nownow - 1week的所有行。 Now是当前时间,脚本已启动。 我不确定如何在迭代中做到这一点(如果可能的话)。 这就是我打开文件并定义 TimeRow 的方式:

for row in f_reader:
    stringRowDate = row[0]
    Date = datetime.datetime.strptime(stringRowDate,"%Y-%m-%d %H:%M")
    stringDateNow = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
    DateNow = datetime.datetime.strptime(stringDateNow,"%Y-%m-%d %H:%M")

csvFile 打开的我的代码:

if Date >= DateNow:
    continue
elif Date >= (DateNow - timedelta(weeks=1)):
    data_Week = {row[0]:row[1:] for row in f_reader}
rownum +=1

data_Week是现在保存文件中从now1 Week之前的所有行的字典。

我可以通过使用相同的迭代将24hours 中的每一行添加到另一个字典 (data_24) 吗?

【问题讨论】:

  • 文件是否按日期排序?
  • 编辑了问题,是的,文件按日期排序

标签: csv python-3.x dictionary iteration


【解决方案1】:

您可以单独检查每一行,而不是将所有其余数据发送到一个字典中:

week_ago = (DateNow - timedelta(weeks=1))
day_ago = (DateNow - timedelta(days=1))
data_Week = {}
data_24 = {}
#data_before = {}

for row in f_reader:
    stringRowDate = row[0]
    Date = datetime.datetime.strptime(stringRowDate,"%Y-%m-%d %H:%M")
    if Date >= day_ago:
        data_24[row[0]] = row[1:]
    elif Date >= week_ago:
        data_Week[row[0]] = row[1:]
    else:
        continue
        #data_before[row[0]] = row[1:]

虽然这意味着如果文件被方便地排序,则不必要地检查许多条件,在这种情况下,您只需跟踪当前的 split_time 以指示何时切换 dict 和 current_data 将指向一个将日期放入的字典:

#first is the value to signal to go to next group
data_sorter = iter([(week_ago,None), #None placeholder to not keep data from before week_ago
                    (day_ago,data_Week),
                    (None,data_24)]) #no split for last one, just take the rest of data until end of reader
split_time,current_data = next(data_sorter)
for row in f_reader:
    stringRowDate = row[0]
    Date = datetime.datetime.strptime(stringRowDate,"%Y-%m-%d %H:%M")
    if split_time is not None and (Date > split_time):
        split_time,current_data = next(data_sorter)
    if current_data is not None: #make sure there is no placeholder
        current_data[row[0]] = row[1:]

根据您的程序中涉及的其他内容,使用生成器可能更方便,因此不需要占位符:

from operator import lt #used only for the default check_f
def split_by_time(reader,*split_times, check_f=lt):
    split_times = iter(split_times)
    split_time = next(split_times,None)
    current_data = {}
    for line in reader:
        row_time,*row_data = line
        if split_time is not None and check_f(split_time,row_time):
            yield current_data
            split_time = next(split_times,None)
            current_data = {}
        current_data[row_time] = row_data
    yield current_data


def check_limit(split_date, date_from_file):
    "convert the string date from file to a datetime object for comparison"
    return split_date < datetime.datetime.strptime(date_from_file,"%Y-%m-%d %H:%M")

times = list(split_by_time(f_reader,
                        week_ago,day_ago, 
                        check_f=check_limit))

print("from before a week ago:\n",times[0])
print("from a week ago to a day ago:\n",times[1])
print("since yesterday:\n",times[2])

但这可能比你真正需要的还要多,我真的很喜欢生成器。 :D

【讨论】:

  • 谢谢,这正是我所需要的 :-) 也感谢生成器的东西,但我认为我不需要它们
  • 我知道,但自从我看到PEP 342 并用这个例子制作了我的第一个协程(非常接近我提供的生成器)后,我就一直渴望制作一个协程,但我怀疑你会有任何用处,因为它的使用方式截然不同。我只是为了制作它的乐趣而制作它!
猜你喜欢
  • 2018-09-03
  • 2023-03-03
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-14
  • 2014-04-12
相关资源
最近更新 更多