Dictionary update replaces original values instead - python

Whenever I receive a new url, I try to add that in my dictionary, along with the current time.
However, when I use the update() method, it replaces original values with the new values I added, so that the only thing in the dictionary now are the new values (and not the old ones).
Here is a shorter version of my code:
if domain not in lst:
lst.append(domain)
domaindict = {}
listofdomains.append(domaindict)
domaindict.update({domain:datetime.now().strftime('%m/%d/%Y %H:%M:%S')})
if domain in lst:
domindex = lst.index(domain)
listofdomains[domindex].update({domain:datetime.now().strftime('%m/%d/%Y %H:%M:%S')})
lst is the list of domain names so far, while listofdomains is the list that contains all the dictionaries of the separate domains (each dictionary has the domain name plus the time).
When I try to print listofdomains:
print(listofdomains)
It only prints out the newly added domain and urls in the dictionaries. I also tried to use other methods to update a dictionary, as detailed in the answers to this question, but my dictionaries are still not functioning properly.
Why did the original key/value pairs dissapear?

The simplest structure would probably be a dict of lists:
data = {domain1:[time1, time2, ...], domain2:[...] ...}
You can build it simply using a defaultdict that creates empty lists on the fly when needed. Your code would be:
from collections import defaultdict
data = defaultdict(list)
and your whole code becomes simply:
data[domain].append(datetime.now().strftime('%m/%d/%Y %H:%M:%S'))

Related

How do I use dictionary to store the filename generated by a method in Python?

I am using a method to generate multiple xml files.
I want to keep track of the files generated by the method using dictionary
map = {}
dstFile = f'path-to-dir\\{self.name}.xml'
with open(dstFile,'w') as f_out:
f_out.write( u'<?xml version="1.0" encoding="UTF-8"?>'+'\n')
f_out.write( ET.tostring(self.root).decode('UTF-8')
map = {f'{self.name}':f'{self.name}.xml'}
But using the map dictionary this way, previous values in the dictionary got overwritten
I want that when the method generate a file, its name will get added to the dictionary keeping the older key value pairs also.
Thanks.
This line
map = {f'{self.name}':f'{self.name}.xml'}
creates a new dictionary and assigns it to the variable map. You want to add a new key-value pair to the existing dictionary.
You can do this the following way:
map[self.name] = f"{self.name}.xml"
You can use dict's method update for example like this:
map.update(f'{self.name}'=f'{self.name}.xml')

Assign many values to an element of a list

If I want to assign to an element of a list only one value I use always a dictionary. For example:
{'Monday':1, 'Tuesday':2,...'Friday':5,..}
But I want to assign to one element of a list many values, like for example:
Monday: Jogging, Swimming, Skating
Tuesday: School, Work, Dinner, Cinema
...
Friday: Doctor
Is any built-in structure or a simple way to make something like this in python?
My idea: I was thinking about something like: a dictionary which as a key holds a day and as a value holds a list, but maybe there is a better solution.
A dictionary whose values are lists is perfectly fine, and in fact very common.
In fact, you might want to consider an extension to that: a collections.defaultdict(list). This will create a new empty list the first time you access any key, so you can write code like this:
d[day].append(activity)
… instead of this:
if not day in d:
d[day] = []
d[day].append(activity)
The down-side of a defaultdict is that you no longer have a way to detect that a key is missing in your lookup code, because it will automatically create a new one. If that matters, use a regular dict together with the setdefault method:
d.setdefault(day, []).append(activity)
You could wrap either of these solutions up in a "MultiDict" class that encapsulates the fact that it's a dictionary of lists, but the dictionary-of-lists idea is such a common idiom that it really isn't necessary to hide it.

How can I initialize and increment an undefined value within a list in Python 3?

What I have is a dictionary of words and I'm generating objects that contain
(1) Original word (e.g. cats)
(2) Alphabetized word (e.g. acst)
(3) Length of the word
Without knowing the length of the longest word, is it possible to create an array (or, in Python, a list) such that, as I scan through the dictionary, it will append an object with x chars into a list in array[x]?
For example, when I encounter the word "a", it will append the generated object to the list at array[1]. Next, for aardvark, if will append the generated object to the list at array[8], etc.
I thought about creating an array of size 1 and then adding on to it, but I'm not sure how it would work.
Foe example: for the first word, a, it will append it to the list stored in array[1]. However, for next word, aardvark, how am I supposed to check/generate more spots in the list until it hits 8? If I append to array, I need give the append function an arg. But, I can't give it just any arg since I don't want to change previously entered values (e.g. 'a' in array[1]).
I'm trying to optimize my code for an assignment, so the alternative is going through the list a second time after I've determined the longest word. However, I think it would be better to do it as I alphabetize the words and create the objects such that I don't have to go through the lengthy dictionary twice.
Also, quick question about syntax: listOfStuff[x].append(y) will initialize/append to the list within listOfStuff at the value x with the value y, correct?
Store the lengths as keys in a dict rather than as indexes in a list. This is really easy if you use a defaultdict from the collections module - your algorithm will look like this:
from collections import defaultdict
results = defaultdict(list)
for word in words:
results[len(word)].append(word)
This ties in to your second question: listOfStuff[x].append(y) will append to a list that already exists at listofStuff[x]. It will not create a new one if that hasn't already been initialised to a (possibly empty) list. If x isn't a valid index to the list (eg, x=3 into a listOfStuff length 2), you'll get an IndexError. If it exists but there is something other than another list there, you will probably get an AttributeError.
Using a dict takes care of the first problem for you - assigning to a non-existent dict key is always valid. Using a defaultdict extends this idea to also reading from a non-existent key - it will insert a default value given by calling the function you give the defaultdict when you create it (in this case, we gave it list, so it calls it and gets an empty list) into the dict the first time you use it.
If you can't use collections for some reason, the next best way is still to use dicts - they have a method called setdefault that works similarly to defaultdicts. You can use it like this:
results = {}
for word in words:
results.setdefault(len(word), []).append(word)
as you can see, setdefault takes two arguments: a key and a default value. If the key already exists in the dict, setdefault just returns its current value as if you'd done results[key]. If that would be an error, however, it inserts the second argument into the dictionary at that key, and then returns it. This is a little bit clunkier to use than defaultdict, but when your default value is an empty list it is otherwise the same (defaultdict is better to use when your default is expensive to create, however, since it only calls the factory function as needed, but you need to precompute it to pass into setdefault).
It is technically possible to do this with nested lists, but it is ugly. You have to:
Detect the case that the list isn't big enough
Figure out how many more elements the list needs
Grow the list to that size
the most Pythonic way to do the first bit is to catch the error (something you could also do with dicts if setdefault and defaultdict didn't exist). The whole thing looks like this:
results = []
for word in words:
try:
results[len(word)]
except IndexError:
# Grow the list so that the new highest index is
# len(word)
new_length = len(word) + 1
difference = len(results) - new_length
results.extend([] for _ in range(difference))
finally:
results[len(word)].append(word)
Stay with dicts to avoid this kind of mess. lists are specifically optimised for the case that the exact numeric index of any element isn't meaningful outside of the list, which doesn't meet your use case. This type of code is really common when you have a mismatch between what your code needs to do and what the data structures you're using are good at, and it is worth learning as early as possible how to avoid it.

Insert Variable Dictionary Values to db

I have a dictionary whose keys and values are updated from internet. This dictionary keeps changing the position and number of its keys/variables on every update (for some reason) but the names of keys and formats of values remain the same. Initially, I converted its keys and values to different arrays and was storing their values to database by following their array locaton, but after I discovered its variability, its no more possible to do it the same way I was doing, since the len(dictionary) keeps changing. The dictionary items are fetched from a url on every update, which sometime gives me 31 items (each item is key:value) and sometime gives me 3, 29 , 28 or even 27 items in the dictionary. So, I have made a generalization about some 'always-there' items and now I want to extract them on every update, but not according to their order, but according to their keys. Its more like: I need to search for specific keywords in the dictionary and to save their corresponding values to the variables. For instance, on one update it's keys are:
>>> len(dict.keys())
>>> 30
on another update:
>>> len(dict.keys())
>>> 26
This shows the number of items in the dictionary keeps variating. However, I have noted a list of some obligatory keys (that I am mentioning below) which are always there so I just need to look for them whenever the thing is updated. In more precise terms, I need a way to extract specific keys (probably by searching) and their corresponding values from the dictionary and to save both them to different variables so that I can save them to database. The keys to be searched are:
temp_f
relative_humidity
wind_dir
pressure_mb
location
Thanks.
If I understood your problem well, you don't need to maintain the order of keys/values in your dictionary and you just want to strip your dictionary from unwanted keys and rename the keys you are interested in. Your concern is that some keys might also be missing. I would solve it in this way.
new_dict = {
'tf' : original_dict.get('temp_f', None),
'rh' : original_dict.get('relative_humidity', None),
# And so on...
}
If you want to maintain the order, use collections.OrderedDict instead of normal dict.

Can't update a dictionary in Python

I'm trying to add some records into a dictionary.
Initially I was doing it this way
licenses = [dict(licenseid=row[0], client=row[1], macaddress=row[2], void=row[18]) for row in db]
But I've since realized I need to do some processing to filter records from db, so I tried changing the code to:
for rec in db:
if rec['deleted'] == False:
licenses.update(dict(licenseid=row[0], client=row[1], macaddress=row[2], void=row[18])
That code runs without exceptions, but I only end up with the last db record in licenses, which is confusing me.
I think licenses is a list:
licenses = []
...
and you should append to it new dictionaries:
licenses.append(dict(...))
If I understand correctly, you want to add multiple records in a single dictionary, right ? Instead of making a list of dictionaries, why wouldn't you make a dictionary of lists instead?
Start by building a list of the keys you'll need (so that you always access them in the same order).
keys = ["licenses", "client", "macaddress", "void"]
Construct an empty dictionary:
licences = dict((k,[]) for k in keys]
Recursively add entries to your dictionary:
for (k,item) in row:
dict[k].append(item)
Of course, it might be easier to build a list of all your records first, and then construct a dictionary at the very end.
Quoth the dict.update() documentation:
update([other]) Update the dictionary with the key/value pairs from
other, overwriting existing keys. Return None.
Which explains why the last update "wins". licences cannot be a list as there is no update method for lists.
If the code in your post is your genuine code, then you might consider replacing row with rec in the last line (the one with the update), because there are chances you're updating your dictionary with always the same values !
Edit: There's obviously something very wrong in this code, from the other answer I see that I overlooked the fact that licenses was declared as a list: so the only explanation for not having an exception is either the snippets you show are not the genuine one or all your record are so that rec['deleted'] is True (so that the update method is never called).
After responses, I've amended my code:
licenses = []
for row in db:
if row.deleted == False:
licenses.append(dict(licenseid=row[0], client=row[1], macaddress=row[2], void=row[18]))
Which now works perfectly. Thanks for spotting my stupidity! ;)

Categories