Dan Von
Dan Von

Reputation: 83

How do I add a new value to a dictionary's key on top of the old one, to create a sum?

I'm trying to continously add a value to a dictionary's key's value, to form a sum of an old and new value.

My code checks if one string [str_1] from now is the same as a string from 1 second ago, [str_2] if it isn't, it should create a key with the key from 1 second ago, store for how long it's been on that string and move on to the next [str_?], repeating the process for a new string (creating a new key), then, if it meets any of the strings stored [str_?], it should take that key's value and add the new value on top of it, to create a sum.

seconds = 0
my_dict = {}
stop = 0

while stop != 1:

    then_string = getStringValue() #Copies a string from somewhere.
    sleep(1)
    now_string = getStringValue() #Copies a string from somewhere, note, we waited 1 sec.

    if then_string == now_string:
        seconds += 1
    elif then_string != now_string:
        my_dict[then_string] = seconds
        """This is where I'm stuck."""
        seconds = 0 #Resets the seconds.
    else:
        pass

My problem is that once I get to the elif (strings changed, alarm for adding new value), it breaks.

It only adds the value of seconds, even if I were to do something like

my_dict[then_string] = my_dict.get(then_string) + seconds

The value is a seemingly doubled number of seconds and it yields improper results.

My goal is to properly get the seconds spent on a string.

Upvotes: 1

Views: 346

Answers (4)

Dom Weldon
Dom Weldon

Reputation: 1738

Dictionary Approach

Going down the dictionary method as per the original post, this would be how I would tackle it. Note the try/except - in place addition will throw a KeyError if the key doesn't yet exist.

seconds = 0
my_dict = {}
stop = 0

while stop != 1:
    then_string = getStringValue() #Copies a string from somewhere.
    sleep(1)
    now_string = getStringValue() #Copies a string from somewhere, note, we waited 1 sec.

    if then_string == now_string:
        seconds += 1
    elif then_string != now_string:
        try:
            # let's assume the key exists
            my_dict[then_string] += seconds
        except KeyError:
            # oh no! it doens't exist, let's set it at seconds
            my_dict[then_string] = seconds
        seconds = 0 #Resets the seconds.
    else:
        pass

Collections Approach

However, python has a special container type for just this task called collections.Counter(), which is an extended dictionary.

from collections import Counter
seconds = 0
my_counter = Counter()
stop = 0

while stop != 1:
    sv = getStringValue()
    c.update(sv = 1)
    sleep(1)
    # do something here to ascertain when to set stop = 1
else:
    del sv
# output a nice count of all sv's and the second count
print(c)

Upvotes: 0

YLJ
YLJ

Reputation: 2996

Check if key then_string exists in my_dict:

Method 1

Use in to check existence.

if then_string in my_dict:
    my_dict[then_string] += second
else:
    my_dict[then_string] = second

Method 2

Use dict.get(key, default_value) to get value or default value if key doesn't exist.

my_dict[then_string] = my_dict.get(then_string, 0) + second

Method 3

Use defaultdict from collection. Reference

from collections import defaultdict
my_dict = defaultdict(int)  # Set default to an int, or 0

my_dict[then_string] += second

Example

The entire code will become

seconds = 0
my_dict = {}
stop = 0
while stop != 1:
    then_string = getStringValue()
    sleep(1)
    now_string = getStringValue()
    if then_string == now_string:
        seconds += 1
    elif then_string != now_string:
        # Modify here.
        if then_string in my_dict:
            my_dict[then_string] += second
        else:
            my_dict[then_string] = second
        seconds = 0
    else:
        pass

Upvotes: 2

henneray
henneray

Reputation: 449

You could use a while loop, which I think is a bit more logical.

then_string = getStringValue()
now_string = then_string

while stop != 1:
    seconds = 0

    while then_string==now_string:
        time.sleep(1)
        seconds += 1
        now_string = getStringValue()

    if then_string in my_dict:
        my_dict[then_string] += seconds
    else:
        my_dict[then_string] = seconds

    then_string = now_string

Upvotes: 0

gbtimmon
gbtimmon

Reputation: 4332

I would utilize pythons object powers. Maybe consider code like this which is a lot simpler.

# Extend dict with a new increment method. 
class increment_dict(dict):                       
    def increment(self, key): 
        # increment increases key by one. 
        # self.get(key,0) will return 0 if key not in self.                     
        self[key] = self.get(key, 0) + 1          


running = True                                    
i_dict = increment_dict()                         

# I dont need to remember what I saw last just increase the count of 
# seconds by on every time I see a string. Both are constant runtime 
# and without string equality this I suspect will be faster.                                             
while running:                                    
    sleep(1)                                      
    i_dict.increment(getStringValue())            

Upvotes: 1

Related Questions