Dictionary update overwrites duplicate keys - list

I have a table that has 6982 records that I am reading through to make a dictionary. I used a literal to create the dictionary
fld_zone_dict = dict()
fields = ['uniqueid', 'FLD_ZONE', 'FLD_ZONE_1']
...
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict[uid] = [old_zone_value, new_zone_value]
However, I noticed that using this method, if a uid has the same value as a previous uid (theoretically, there could be duplicate), the entry gets overwritten. So, if I had 2 entries I wanted to add: 'CA10376036': ['AE', 'X'] and 'CA10376036': ['V', 'D'], the first one gets overwritten and I only get 'CA10376036': ['V', 'D']. How can I add to my dictionary with out overwriting the duplicate keys so that I get something like this?
fld_zone_dict = {'CA10376036': ['AE', 'X'], 'CA9194089':['D', 'X'],'CA10376036': ['V', 'D']....}

Short answer: There is no way to have duplicate keys in a dictionary object in Python.
However, if you were to restructure your data and take that key and put it inside of a dictionary that is nested in a list, you could have duplicate IDs. EX:
[
{
"id": "CA10376036",
"data: ['AE', 'X']
},
{
"id": "CA10376036",
"data: ['V', 'D']
},
]
Doing this though will negate any benefits of lookup speed and ease.
edit: blhsing also has a good example of how to restructure data with a reduced initial lookup time, though you would still have to iterate through data to get the record you wanted.

Dicts are not allowed to have duplicate keys in Python. You can use the dict.setdefault method to convert existing keys to a list instead:
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict.setdefault(uid, []).append([old_zone_value, new_zone_value])
so that fld_zone_dict will become like:
{'CA10376036': [['AE', 'X'], ['V', 'D']], 'CA9194089': ['D', 'X'], ...}
but then other keys will not have a list of lists as values, so you probably should convert them all instead:
for k, v in fld_zone_dict.items():
fld_zone_dict[k] = [v]
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict[uid].append([old_zone_value, new_zone_value])
so that fld_zone_dict will become like:
{'CA10376036': [['AE', 'X'], ['V', 'D']], 'CA9194089': [['D', 'X']], ...}

Related

Convert dictionary into list based on the keys

I am trying to convert my dictionary into list, with the same order of keys and values and inserting the line after end of each key values.
For example, I have the following:
mydict = {'Ball' : ['red', 'green'], 'Bat':['white', 'black'], 'wickets': ['white']}
I am trying to make as follows:
reqlist = ['Ball','red', 'green','\n', 'Bat','white', 'black', '\n', 'wickets','white', \n']
This is the code, I have tried:
reqlist = []
for k,v in mydict.iteritems():
for val in v:
reqlist.append([k+val+'\n'])
But, I do not get the expected output.
Pleased to hear some suggestions.
Thanks a lot in advance.
You are appending the key each time you are appending a value. Just pull it out of the loop, along with the new line.
reqlist = []
for k,v in mydict.iteritems():
reqlist.append(k)
for val in v:
reqlist.append(val)
reqlist.append('\n')

How do I append a dictionary item to a pre-existing dictionary in Python?

I have a .csv file containing tweets and their sentiment polarity. Using DictReader, I see each row in the file in the format:
Sentiment: '0', SentimentText: 'xyz'
Now I want to add each row of the file to a pre-existing dictionary such that the structure of the dictionary at the end is:
{{Sentiment: '0', SentimentText: 'xyz'},
{Sentiment: '1', SentimentText: 'abc'}...#so on until eof}
Is there any way that this is possible?
EDIT: So far, this is what I have achieved. This basically makes a list of dictionaries:
dataset = []
with open('SentimentAnalysisDataset.csv') as csvfile:
reader = csv.DictReader(csvfile)
count = 1
for row in reader:
data = [{'Text': row['SentimentText'], 'Polarity': row['Sentiment']}]
tuple = {str(count): data}
count = count + 1
dataset.append(tuple)
This:
{{Sentiment: '0', SentimentText: 'xyz'},
{Sentiment: '1', SentimentText: 'abc'}...#so on until eof}
Is not a valid dictionary structure. If you wish to use a list, this will work:
[{Sentiment: '0', SentimentText: 'xyz'},
{Sentiment: '1', SentimentText: 'abc'}...#so on until eof]
Otherwise, you're probably looking for a structure like this:
{'0': 'xyz',
'1': 'abc',
...}
In order to do that, you should update the existing dictionary like so:
existing_dict = {'0': 'xyz',
'1': 'abc'}
existing_dict[row['Sentiment']] = row['SentimentText']
# OR
new_dict = {row['Sentiment']: row['SentimentText'],
... # For all sentiments in file
}
existing_dict.update(new_dict)

Turning weekly to monthly data in Python dictionary

I'm trying to turn this dictionary:
dic = {'2007-10-21': '53', '2007-10-28': '50', '2007-11-05': '100','2007-11-06': '99'}
Into something like this:
dic = {'2007-10': '103', '2007-11': '199'}
Since I need to do that in scale, pythonly speaking I need to sum all the values which its keys start with the same 7 characters.
Try this,
__author__ = 'Fawzan'
dic = {'2007-10-21': '53', '2007-10-28': '50', '2007-11-05': '100', '2007-11-06': '99'}
# create a new dictionary
newDic = {}
# iterate the old dictionary
for key in dic:
# get the desiresd string for comparision
k = key[0:7]
# for debug
print(k)
# if the key is already in the new dictionary, then add the value to existing key
if (k in newDic):
newDic[k] += float(dic[key])
# else append the key, value
else:
newDic[k] = float(dic[key])
# print and check the answer :)
print(newDic)

How to split and extract each tagname from the list of tags which is in the json data?

"tags" : "['x', 'y', 'z']"
I want to extract each element and add each element to a tag table like
tag1 = x
tag2 = y
tag3 = z
I need to store each tag in tags table in different rows for a event.
table: Event
id, title, ...
table: Tag
Tagid, eventid, tagname
Tags can vary for each event.
Or without eval:
t = {"tags" : "['x', 'y', 'z']"}
tags = [el.replace("'","").strip() for el in t['tags'][1:-1].split(',')]
# Basic string splitting:
tags = t['tags'].split(',')
# To replace a character in a string, like "z"
"a123".replace("a", "b") => "b123
# To strip whitespace:
" Wow ".strip() => "Wow"
# Then, a list comprehension to loop through elements of an array and put them in new array:
x = [1, 2, 3]
y = [i+1 for i in x] => [2, 3, 4]
# All together, this becomes
tags = [el.replace("'","").strip() for el in t['tags'][1:-1].split(',')]
Some say eval is evil, because it's subject to code injection, and therefore possibly unpredictable. But as long as you trust the input, it should be okay. Using ast.literal_eval is much better than eval, as it only evaluates to basic types, and so you don't have to worry about the code injection.
>>> t = {"tags" : "['x', 'y', 'z']"}
>>> import ast
>>> ast.literal_eval(t['tags'])
['x', 'y', 'z']
And now it's a list.
from answer given by Ignacio Vazquez-Abrams I am able to change it into list as below:
tags = ast.literal_eval(tags) #converted to the list
##Stored the tags with event_id in the tags table.
eventobj = Event.objects.get(pk=1)
for i in range(len(tags)):
tagsobj = Tags.objects.create(name = tags[i], event_id = eventobj.pk)
tagsobj.save()

How do I create a dictionary mapping strings to sets given a list and a tuple of tuples?

I am trying to create a dictionary from a list and tuple of tuples as illustrated below. I have to reverse map the tuples to the list and create a set of non-None column names.
Any suggestions on a pythonic way to achieve the solution (desired dictionary) is much appreciated.
MySQL table 'StateLog':
Name NY TX NJ
Amy 1 None 1
Kat None 1 1
Leo None None 1
Python code :
## Fetching data from MySQL table
#cursor.execute("select * from statelog")
#mydataset = cursor.fetchall()
## Fetching column names for mapping
#state_cols = [fieldname[0] for fieldname in cursor.description]
state_cols = ['Name', 'NY', 'TX', 'NJ']
mydataset = (('Amy', '1', None, '1'), ('Kat', None, '1', '1'), ('Leo', None, None, '1'))
temp = [zip(state_cols, each) for each in mydataset]
# Looks like I can't do a tuple comprehension for the following snippet : finallist = ((eachone[1], eachone[0]) for each in temp for eachone in each if eachone[1] if eachone[0] == 'Name')
for each in temp:
for eachone in each:
if eachone[1]:
if eachone[0] == 'Name':
k = eachone[1]
print k, eachone[0]
print '''How do I get a dictionary in this format'''
print '''name_state = {"Amy": set(["NY", "NJ"]),
"Kat": set(["TX", "NJ"]),
"Leo": set(["NJ"])}'''
Output so far :
Amy Name
Amy NY
Amy NJ
Kat Name
Kat TX
Kat NJ
Leo Name
Leo NJ
Desired dictionary :
name_state = {"Amy": set(["NY", "NJ"]),
"Kat": set(["TX", "NJ"]),
"Leo": set(["NJ"])}
To be really honest, I would say your problem is that your code is becoming too cumbersome. Resist the temptation of "one-lining" it and create a function. Everything will become way easier!
mydataset = (
('Amy', '1', None, '1'),
('Kat', None, '1', '1'),
('Leo', None, None, '1')
)
def states(cols, data):
"""
This function receives one of the tuples with data and returns a pair
where the first element is the name from the tuple, and the second
element is a set with all matched states. Well, at least *I* think
it is more readable :)
"""
name = data[0]
states = set(state for state, value in zip(cols, data) if value == '1')
return name, states
pairs = (states(state_cols, data) for data in mydataset)
# Since dicts can receive an iterator which yields pairs where the first one
# will become a key and the second one will become the value, I just pass
# a list with all pairs to the dict constructor.
print dict(pairs)
The result is:
{'Amy': set(['NY', 'NJ']), 'Leo': set(['NJ']), 'Kat': set(['NJ', 'TX'])}
Looks like another job for defaultdict!
So lets create our default dict
name_state = collections.defaultdict(set)
We now have a dictionary that has sets as all default values, we can now do something like this
name_state['Amy'].add('NY')
Moving on you just need to iterate over your object and add to each name the right states. Enjoy
You can do this as a dictionary comprehension (Python 2.7+):
from itertools import compress
name_state = {data[0]: set(compress(state_cols[1:], data[1:])) for data in mydataset}
or as a generator expression:
name_state = dict((data[0], set(compress(state_cols[1:], data[1:]))) for data in mydataset)