Python Create a Dictionary of Lists - python

Alright I searched, but I did not find an answer to my specific problem. I am creating a dictionary of lists. I have while loop creating a few lists of values as well as a name to associate with it:
dict = {}
list = [1, 2]
name = key1
list = [3, 4]
name = key1
If the name is the same, the list will be appended to the existing set of values for the key. Here is the code I have:
if key in dict:
dict[key].append(list)
else:
dict[key] = list
This is the output I want:
dictionary = {'key1': [1, 2], [3, 4]}
However I keep getting this output:
dictionary = {'key1': [1, 2, [3, 4]]}
where the second list to the key is being put inside of the first list.

This is a very common error. I am fairly certain that you are doing:
list1.append(list2)
Instead, you want to do:
list1.extend(list2)
Here is a very useful resource
However, since you want [[1,2], [3,4]] instead of [1,2,3,4], you should do:
if key in d1:
d1[key].append(l1)
else:
d1[key] = [l1]

That is because you are appending a list to a list each time. You need to use extend instead. Code:
keys = ['name1', 'name2', 'name2', 'name1']
somelist = [1, 2, 3]
d = {}
for k in keys:
d.setdefault(k, []).extend(somelist)

You need a list of list in fact, your output will look like this:
dictionary = {'key1': [[1, 2], [3, 4]]}
To have a key associated to multiple values you could use this line:
dictionary.setdefault(key, []).append(a_list)
setdefault will associate the key to the default value [] if the key is not present in your dictionary.
Also you should avoid using dict or list to define your own variables, they are built-in and you are redefining them.
Edit
To make it obvious to the reader maybe this could help, its the output of an interative python session:
>>> d = {}
>>> d.setdefault('key1', []).append([1, 2])
>>> d.setdefault('key1', []).append([3, 4])
>>> d
{'key1': [[1, 2], [3, 4]]}

I hope not misunderstand , since dictionary = {'key1': [1, 2], [3, 4]} is poorly expressed
def add2dict(d, l, k):
if not k in d:
dict[k] = []
d[k].append(l)
dict = {}
add2dict(dict, [1,2], "key1")
add2dict(dict, [3,4], "key1")
result in dict:
{'key1': [[1, 2], [3, 4]]}

Related

Python Dictionary: Replace values based on key occurrence in other values

My question might involve comprehension if I'm not mistaken.
So I have a dictionary as:
data = {
1: [2, 4],
2: [3],
3: [1, 2, 6],
4: [1, 3, 6],
6: [3, 4]
}
I wish to rearrange the dictionary values (not keys) such that with every occurrence of a "key" in any of the other values, the current key's values should now contain the "key" in who's value it originally occurred.
For example the dictionary should now look like this:
new_data = {
1: [3, 4],
2: [1, 3],
3: [2, 4, 6],
4: [1, 6],
6: [3, 4]
}
I know for sure that I must use another empty dictionary to solve this, and I must use looping. I have a starting point, but it's not efficient:
for pk,pv in zip(data.keys(), data.values()):
#print(pk,pv)
for pvs in pv:
#print(pvs)
if pk == pvs:
new_data.setdefault(pk, [])
new_data[pk].append(pvs)
print(new_data)
Any help is appreciated. Thanks in advance :)
(Using Ubuntu 14.04 32-Bit VM and Python 2.7)
Perhaps this is not the most efficient way to do this, but I would argue it's one of the nicest to read :).
One thing I should say before, if it's possible to change the initial dictionary values to set instead of list, that could result in some performance gains since set membership checks can be faster than listss.
Here goes:
def present_in(k, d):
return {idx for idx in d if k in d[idx]}
new_data = {k: present_in(k, data) for k in data}
Basically the present_in function creates a set of values corresponding to keys where k is present as a member. We simply then use this to create the new_data dictionary using a dictionary comprehension. Note again the values of this dictionary is a set, instead of a list. You can easily wrap them in list() if you do need lists.
EDIT:
If you would like new_data to have keys that may be missing as keys in data but present as one of the values, you can change the code to create a set of all possible keys first:
all_keys = {v for vs in data.values() for v in vs}
def present_in(k, d):
return {idx for idx in d if k in d[idx]}
new_data = {k: present_in(k, data) for k in all_keys}
{k:[i for i,j in data.items() if k in j] for k,_ in data.items()}
#Output:
#{1: [3, 4], 2: [1, 3], 3: [2, 4, 6], 4: [1, 6], 6: [3, 4]}
The below part essentially checks if the key(k from outer dict) is present in any of the values in dict, if present, it'll get the corresponding key into the list
[i for i,j in data.items() if k in j]

How do I append multiple lists to one key in a python dictionary?

I want to append values to a key in a dictionary, where the values are actually lists. There could be one list, or there could be multiple lists.
The current way I'm trying to do it, the new list I try to add on just overwrites the last list. As far as I can tell, I can't append a list to a dict like so either:
my_dict.append(my_list))
Current code that overwrites each other:
urls[domain] = [uri, datecreated]
Is this possible? If so, how?
Sample results would look like this
print all keys and values in urls{}:
google.com : ['/helloworld', 2010-04-02], ['/apage/anotherpage', 2015-09-12]
microsoft.com : ['/awebpage', 2009-02-01], ['/bananas', 2015-12-24], ['/anothergreaturi', 205-12-10]
You can have each dictionary entry a list, so you append to that list.
>>> a = Linter("ahahah")
>>> a.write_file()
>>> a = dict()
>>> a["first"] = []
>>> a["first"].append([1,2,3])
>>> a["first"].append([4,5,6])
>>> a["second"] = []
>>> a["second"].append([7,8,9])
>>> a
{
'second':[
[7, 8, 9]
],
'first': [
[1, 2, 3],
[4, 5, 6]
]
}
but honestly, at some point just consider using classes?
Is this what you are trying to achieve?
>>> d={'a': ['b']}
>>> d['a']
['b']
>>> d['a'] += ['c']
>>> d['a']
['b', 'c']
You can use a defaultdict to accomplish what you need.
from collections import defaultdict
my_dict = defaultdict(list)
my_dict[1].append([1,2])
my_dict[1].append([3,4])
my_dict[2].append([8,9])
Now you can access each key element as you would access a dictionary
>>> my_dict[1]
[[1, 2], [3, 4]]
>>> for k, v in my_dict.iteritems():
print k,v
1 [[1, 2], [3, 4]]
2 [[8, 9]]
class My_Dictionary(dict):
def __init__(self):
self = dict()
def add(self, key, value):
try:
self[key].append(value)
except KeyError:
self[key] = [value]
if __name__ == '__main__':
dict_obj = My_Dictionary()
key = 0
take_1 = [1,6,2,4]
take_2 = [7,3,5,6]
dict_obj.add(key, take_1)
dict_obj.add(key, take_2)
print(dict_obj)
This code will return a dictionary in your desired format.
{0: [[1, 6, 2, 4], [7, 3, 5, 6]]}

Find multiple occuring string in array and output index

I have a array filled with e-mail addresses which change constantly. e.g.
mailAddressList = ['chip#plastroltech.com','spammer#example.test','webdude#plastroltech.com','spammer#example.test','spammer#example.test','support#plastroltech.com']
How do I find multiple occurrences of the same string in the array and output it's indexes?
just group indexes by email and print only those items, where lenght of index list is greater than 1:
from collections import defaultdict
mailAddressList = ['chip#plastroltech.com',
'spammer#example.test',
'webdude#plastroltech.com',
'spammer#example.test',
'spammer#example.test',
'support#plastroltech.com'
]
index = defaultdict(list)
for i, email in enumerate(mailAddressList):
index[email].append(i)
print [(email, positions) for email, positions in index.items()
if len(positions) > 1]
# [('spammer#example.test', [1, 3, 4])]
Try this:
query = 'spammer#example.test''
indexes = [i for i, x in enumerate(mailAddressList) if x == query]
Output:
[1, 3, 4]
In [7]: import collections
In [8]: q=collections.Counter(mailAddressList).most_common()
In [9]: indexes = [i for i, x in enumerate(mailAddressList) if x == q[0][0]]
In [10]: indexes
Out[10]: [1, 3, 4]
note: solutions submitted before are more pythonic than mine. but in my opinon, lines that i've written before are easier to understand. i simply will create a dictionary, then will add mail adresses as key and the indexes as value.
first declare an empty dictionary.
>>> dct = {}
then iterate over mail adresses (m) and their indexes (i) in mailAddressList and add them to dictionary.
>>> for i, m in enumerate(mailAddressList):
... if m not in dct.keys():
... dct[m]=[i]
... else:
... dct[m].append(i)
...
now, dct looks liike this.
>>> dct
{'support#plastroltech.com': [5], 'webdude#plastroltech.com': [2],
'chip#plastroltech.com': [0], 'spammer#example.test': [1, 3, 4]}
there are many ways to grab the [1,3,4]. one of them (also not so pythonic :) )
>>> [i for i in dct.values() if len(i)>1][0]
[1, 3, 4]
or this
>>> [i for i in dct.items() if len(i[1])>1][0] #you can add [1] to get [1,3,4]
('spammer#example.test', [1, 3, 4])
Here's a dictionary comprehension solution:
result = { i: [ k[0] for k in list(enumerate(mailAddressList)) if k[1] == i ] for j, i in list(enumerate(mailAddressList)) }
# Gives you: {'webdude#plastroltech.com': [2], 'support#plastroltech.com': [5], 'spammer#example.test': [1, 3, 4], 'chip#plastroltech.com': [0]}
It's not ordered, of course, since it's a hash table. If you want to order it, you can use the OrderedDict collection. For instance, like so:
from collections import OrderedDict
final = OrderedDict(sorted(result.items(), key=lambda t: t[0]))
# Gives you: OrderedDict([('chip#plastroltech.com', [0]), ('spammer#example.test', [1, 3, 4]), ('support#plastroltech.com', [5]), ('webdude#plastroltech.com', [2])])
This discussion is less relevant, but it might also prove useful to you.
mailAddressList = ["chip#plastroltech.com","spammer#example.test","webdude#plastroltech.com","spammer#example.test","spammer#example.test","support#plastroltech.com"]
print [index for index, address in enumerate(mailAddressList) if mailAddressList.count(address) > 1]
prints [1, 3, 4], the indices of the addresses occuring more than once in the list.

Intersection of subelements of multiple list of lists in dictionary

I have a number of lists of lists stored in a dictionary. I want to find the intersection of the sub-lists (i.e. intersection of dict[i][j]) for all keys of the dictionary. )
For example, if the dictionary stored sets of tuples instead, I could use the code:
set.intersection(*[index[key] for key in all_keys])
What is an efficient way to do this? One way I tried was to first convert each list of lists into a set of tuples and then taking the intersection of those, but this is rather clunky.
Example:
Suppose the dictionary of lists of lists is
dict = {}
dict['A'] = [[1, 'charlie'], [2, 'frankie']]
dict['B'] = [[1, 'charlie'], [2, 'chuck']]
dict['C'] = [[2, 'chuck'], [1, 'charlie']]
then I want to return
[1, 'charlie']
(maybe as a tuple, doesn't have to be list)
EDIT: I just found an okay way to do it, but it's not very 'pythonic'
def search(index, search_words):
rv = {tuple(t) for t in index[search_words[0]]}
for word in search_words:
rv = rv.intersection({tuple(t) for t in index[word]})
return rv
Let's call your dictionary of lists of lists d:
>>> d = {'A': [[1, 'charlie'], [2, 'frankie']], 'B': [[1, 'charlie'], [2, 'chuck']], 'C': [[2, 'chuck'], [1, 'charlie']]}
I am calling it d because dict is a builtin and we would prefer not to overwrite it.
Now, find the intersection:
>>> set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
set([(1, 'charlie')])
How it works
set(tuple(x) for x in d[k])
For key k, this forms a set out of tuples of the elements in d[k]. Taking k='A' for example:
>>> k='A'; set(tuple(x) for x in d[k])
set([(2, 'frankie'), (1, 'charlie')])
[ set(tuple(x) for x in d[k]) for k in d ]
This makes a list of the sets from the step above. Thus:
>>> [ set(tuple(x) for x in d[k]) for k in d ]
[set([(2, 'frankie'), (1, 'charlie')]),
set([(2, 'chuck'), (1, 'charlie')]),
set([(2, 'chuck'), (1, 'charlie')])]
set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
This gathers the intersection of the three sets as above:
>>>set.intersection( *[ set(tuple(x) for x in d[k]) for k in d ] )
set([(1, 'charlie')])
[item for item in A if item in B+C]
Your usecase demands the use of reduce function. But, quoting the BDFL's take on reduce,
So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.
So, what you have got is already 'pythonic'.
I would write the program like this
>>> d = {'A': [[1, 'charlie'], [2, 'frankie']],
... 'B': [[1, 'charlie'], [2, 'chuck']],
... 'C': [[2, 'chuck'], [1, 'charlie']]}
>>> values = (value for value in d.values())
>>> result = {tuple(item) for item in next(values)}
>>> for item in values:
... result &= frozenset(tuple(items) for items in item)
>>> result
set([(1, 'charlie')])
from collections import defaultdict
d = {'A': [[1, 'charlie'], [2, 'frankie']], 'B': [[1, 'charlie'], [2, 'chuck']], 'C': [[2, 'chuck'], [1, 'charlie']]}
frequency = defaultdict(set)
for key, items in d.iteritems():
for pair in items:
frequency[tuple(pair)].add(key)
output = [
pair for pair, occurrances in frequency.iteritems() if len(d) == len(occurrances)
]
print output

How to add values in keys in a dictionary inside a loop?

I have the following list:
x=['a','3','4','b','1','2','c','4','5']
How can i make the following dictionary:
b = {'a':[3,4],'b':[1,2],'c':[4,5]}
I tried the following:
Category = defaultdict(int)
for i in a:
if Varius.is_number(i)==False:
Category[i]=[]
keys.append(i)
else:
Category[keys(i)] = i
The keys are created but after i have problem to insert the values.(is_number is a function which check if the value of the list is number or string).First day away of MATLAB.First day in Python..
Here an example that actually uses the feature that defaultdict provides over the normal dict:
from collections import defaultdict
x=['a','3','4','b','1','2','c','4','5']
key='<unknown>' # needed if the first value of x is a number
category = defaultdict(list) # defaultdict with list
for i in x:
if i.isalpha():
key = i;
else:
category[key].append(i) # no need to initialize with an empty list
print category
Also: you should use lower case names for class instances. Uppercase names are usually reserved for classes. Read pep8 for a style guide.
If the key/value entries in your list x are evenly spaced, here's an alternative way to build the dictionary. It uses a few of Python's built in features and functions:
>>> keys = x[::3]
>>> values = [map(int, pair) for pair in zip(x[1::3], x[2::3])]
>>> dict(zip(keys, values))
{'a': [3, 4], 'b': [1, 2], 'c': [4, 5]}
To explain what's being used here:
list slicing to create new lists from x: x[start:stop:step]
here zip takes two lists and makes a list of tuples containing the n-th elements of each list
map(int, pair) turns a tuple of digit strings into a list of integers
values is constructed with list comprehension - the map function is applied to each pair
dict turns a list of pairs into dictionary keys/values
You can use itertools.groupby :
>>> from itertools import groupby
>>> l=[list(g) for k,g in groupby(x,lambda x : x.isalpha())]
>>> p=[l[i:i+2] for i in range(0,len(l),2)]
>>> {i[0]:map(int,j) for i,j in p}
{'a': [3, 4], 'c': [4, 5], 'b': [1, 2]}
Assuming you have a key on the first positions of your list (x) and that after a letter, there will be a number:
from collections import defaultdict
x=['a','3','4','b','1','2','c','4','5']
key = x[0]
Category = defaultdict(int)
for i in x:
if i.isalpha():
key = i;
else:
Category[key].append(i)
print Category
Using itertools.groupby and some iterator stuff:
>>> from itertools import groupby
>>> it = (next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha))
>>> {k: next(it) for k in it}
{'a': [3, 4], 'c': [4, 5], 'b': [1, 2]}
Here the first iterator will yield something like:
>>> [next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha)]
['a', [3, 4], 'b', [1, 2], 'c', [4, 5]]
Now as this iterator is going to yield key-value alternately, we can loop over this iterator and get the next item from it(i.e the value) using next()
>>> it = (next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha))
>>> for k in it:
print k,'-->' ,next(it)
...
a --> [3, 4]
b --> [1, 2]
c --> [4, 5]
There's another way to consume this iterator that is using zip, but it's a little hard to understand IMO:
>>> it = (next(g) if k else map(int, g) for k, g in groupby(x, str.isalpha))
>>> dict(zip(*[it]*2))
{'a': [3, 4], 'c': [4, 5], 'b': [1, 2]}
Simple solution using just dict and list:
>>> category = {}
>>> for i in x:
... if i.isalpha():
... items = category[i] = []
... elif category:
... items.append(i)
...
>>> print(category)
{'c': ['4', '5'], 'a': ['3', '4'], 'b': ['1', '2']}

Categories

Resources