Home > Net >  Generating a nested dictionary in Python through iterations
Generating a nested dictionary in Python through iterations

Time:07-19

I'm new in Python and I have to retrieve datas from a txt file (which I have already did) and then I need to make a nested dictionary like this:

new_dict = {"2009-10-16": {"KitchenSensor":"active for x minutes today", 
                              "BathroomSensor":"active for y minutes today"...}
               "2009-10-24":{"KitchenSensor":"active for x minutes today", 
                              "BathroomSensor":"active for y minutes today"...}
                 "2009-11-13":{"KitchenSensor":"active for x minutes today", 
                              "BathroomSensor":"active for y minutes today"...}}

my code looks like this

namesFile = open("data.txt", "r")  
listaDati = namesFile.readlines()  

listaDivisa = []
for i in listaDati:
    if i[27] != "T":
        listaDivisa.append(
            i.split())  

and the datas in my txt file have this format:

2009-10-16 00:01:04.000059  KITCHENSENSOR ON

2009-10-16 02:33:12.000093  KITCHENSENSOR OFF

2009-10-24 21:25:52.000023  BATHROOMSENSOR ON

2009-10-24 23:13:52.000014  BATHROOMSENSOR OFF

2009-11-13 09:03:23.000053  BATHROOMSENSOR ON

2009-11-13 12:13:42.000014  BATHROOMSENSOR OFF

the timestamp changes every now and then so I want to create a new key with the new timestamp everytime I meet a new one and saving the infos I have to save. I was trying doing this with an enumerative for loop but I don't understand how I can create the dictionary.

Thank you!

CodePudding user response:

You're maybe looking for something like this; I separated the task into

  1. parsing the input lines (could be from a file, but here they're just a list) into events (3-tuples of datetime, sensor name and state)
  2. grouping the events by date, and looking at the state changes.
import datetime
from itertools import groupby


def parse_line(line):
    # Split the line at the two spaces.
    time_string, event = line.split("  ", 1)
    # Split the rest of the line at one space.
    sensor, event = event.split(" ", 1)
    # Parse the time string to a real datetime object.
    t = datetime.datetime.strptime(time_string, "%Y-%m-%d %H:%M:%S.%f")
    return (t, sensor, event == "ON")


def collate_sorted_events(sorted_events):
    zero_delta = datetime.timedelta(0)
    for day, events in groupby(
        sorted_events, lambda event_triple: event_triple[0].date()
    ):
        # We're assuming all sensors start off each day.
        turn_on_times = {}
        durations = {}
        for time, sensor, state in events:
            if state:  # Turning on?
                # If it was on already, that's not an issue; we just consider that a glitch.
                if sensor not in turn_on_times:
                    turn_on_times[sensor] = time
            else:
                if sensor not in turn_on_times:
                    raise ValueError("Sensor was turned off before it was turned on.")
                this_duration = time - turn_on_times[sensor]
                durations[sensor] = durations.get(sensor, zero_delta)   this_duration
                del turn_on_times[sensor]
        yield (day, durations)
        if turn_on_times:
            # This check could be removed, but for now it's a good sanity check...
            raise ValueError(
                "Some sensors were left on at the end of the day; this could be a problem"
            )


listaDati = [
    "2009-10-16 00:01:04.000059  KITCHENSENSOR ON",
    "2009-10-16 02:33:12.000093  KITCHENSENSOR OFF",
    "2009-10-24 21:25:52.000023  BATHROOMSENSOR ON",
    "2009-10-24 23:13:52.000014  BATHROOMSENSOR OFF",
    "2009-11-13 09:03:23.000053  BATHROOMSENSOR ON",
    "2009-11-13 12:13:42.000014  BATHROOMSENSOR OFF",
]

# Parse and sort input lines.  It's imperative that the events are sorted
# so the rest of the code works as it should.
sorted_events = sorted(parse_line(i) for i in listaDati)

# Collate events by day; the function yields day/durations tuples,
# and `dict` accepts that format to create a dict with.
output = dict(collate_sorted_events(sorted_events))
print(output)
for date, deltas in sorted(output.items()):
    for sensor, delta in sorted(deltas.items()):
        print(f"{date} {sensor} {delta.total_seconds() / 60:.2f} minutes")

The output is

{
  datetime.date(2009, 10, 16): {'KITCHENSENSOR': datetime.timedelta(seconds=9128, microseconds=34)},
  datetime.date(2009, 10, 24): {'BATHROOMSENSOR': datetime.timedelta(seconds=6479, microseconds=999991)},
  datetime.date(2009, 11, 13): {'BATHROOMSENSOR': datetime.timedelta(seconds=11418, microseconds=999961)},
}

followed by the formatted

2009-10-16 KITCHENSENSOR 152.13 minutes
2009-10-24 BATHROOMSENSOR 108.00 minutes
2009-11-13 BATHROOMSENSOR 190.32 minutes
  • Related