Im trying to print specific value in this dictionary compiled of several list.
the_dic = {'k1':[1,2,3,{'tricky':['oh','man','inception',{'target':[1,2,3,'hello']}]}]}
Expected output: hello
Can i expand from this simple code below?
print(the_dic["k1"])
You can keep indexing further by referring to the specific index (of the list) [3] or further keys in the dictionary!
This works because the result of each indexing or key reference returns the inner value, which exposes its own methods for indexing or referring to its keys (or a single value, ending your chain!) depending on the inner type
Continuing the chain little further
>>> d = {'k1':[1,2,3,{'tricky':['oh','man','inception',{'target':[1,2,3,'hello']}]}]}
>>> d["k1"]
[1, 2, 3, {'tricky': ['oh', 'man', 'inception', {'target': [1, 2, 3, 'hello']}]}]
>>> d["k1"][3]
{'tricky': ['oh', 'man', 'inception', {'target': [1, 2, 3, 'hello']}]}
>>> d["k1"][3]["tricky"]
['oh', 'man', 'inception', {'target': [1, 2, 3, 'hello']}]
Offering a simpler example, it may be clearer still
>>> d = {'a': {'b': [1,2,3]}}
>>> d['a']['b'] # list referenced by key 'b' within key 'a' of d
[1, 2, 3]
>>> d['a']['b'][0] # first member of the very innermost list
1
I think for your desired output your final code will be:
the_dic = {'k1':[1,2,3,{'tricky':['oh','man','inception',{'target':[1,2,3,'hello']}]}]}
print(the_dic['k1'][3]['tricky'][3]['target'][3])
Result:
hello
A helper recursive function such as this should do the trick:
def get_last_val(d):
if isinstance(d, list):
return get_last_val(d[-1])
if isinstance(d, dict):
return get_last_val(d.popitem()[1])
return d
Example:
>>> get_last_val(the_dic)
'hello'
Related
My attempt to programmatically create a dictionary of lists is failing to allow me to individually address dictionary keys. Whenever I create the dictionary of lists and try to append to one key, all of them are updated. Here's a very simple test case:
data = {}
data = data.fromkeys(range(2),[])
data[1].append('hello')
print data
Actual result: {0: ['hello'], 1: ['hello']}
Expected result: {0: [], 1: ['hello']}
Here's what works
data = {0:[],1:[]}
data[1].append('hello')
print data
Actual and Expected Result: {0: [], 1: ['hello']}
Why is the fromkeys method not working as expected?
When [] is passed as the second argument to dict.fromkeys(), all values in the resulting dict will be the same list object.
In Python 2.7 or above, use a dict comprehension instead:
data = {k: [] for k in range(2)}
In earlier versions of Python, there is no dict comprehension, but a list comprehension can be passed to the dict constructor instead:
data = dict([(k, []) for k in range(2)])
In 2.4-2.6, it is also possible to pass a generator expression to dict, and the surrounding parentheses can be dropped:
data = dict((k, []) for k in range(2))
Try using a defaultdict instead:
from collections import defaultdict
data = defaultdict(list)
data[1].append('hello')
This way, the keys don't need to be initialized with empty lists ahead of time. The defaultdict() object instead calls the factory function given to it, every time a key is accessed that doesn't exist yet. So, in this example, attempting to access data[1] triggers data[1] = list() internally, giving that key a new empty list as its value.
The original code with .fromkeys shares one (mutable) list. Similarly,
alist = [1]
data = dict.fromkeys(range(2), alist)
alist.append(2)
print(data)
would output {0: [1, 2], 1: [1, 2]}. This is called out in the dict.fromkeys() documentation:
All of the values refer to just a single instance, so it generally doesn’t make sense for value to be a mutable object such as an empty list.
Another option is to use the dict.setdefault() method, which retrieves the value for a key after first checking it exists and setting a default if it doesn't. .append can then be called on the result:
data = {}
data.setdefault(1, []).append('hello')
Finally, to create a dictionary from a list of known keys and a given "template" list (where each value should start with the same elements, but be a distinct list), use a dictionary comprehension and copy the initial list:
alist = [1]
data = {key: alist[:] for key in range(2)}
Here, alist[:] creates a shallow copy of alist, and this is done separately for each value. See How do I clone a list so that it doesn't change unexpectedly after assignment? for more techniques for copying the list.
You could use a dict comprehension:
>>> keys = ['a','b','c']
>>> value = [0, 0]
>>> {key: list(value) for key in keys}
{'a': [0, 0], 'b': [0, 0], 'c': [0, 0]}
This answer is here to explain this behavior to anyone flummoxed by the results they get of trying to instantiate a dict with fromkeys() with a mutable default value in that dict.
Consider:
#Python 3.4.3 (default, Nov 17 2016, 01:08:31)
# start by validating that different variables pointing to an
# empty mutable are indeed different references.
>>> l1 = []
>>> l2 = []
>>> id(l1)
140150323815176
>>> id(l2)
140150324024968
so any change to l1 will not affect l2 and vice versa.
this would be true for any mutable so far, including a dict.
# create a new dict from an iterable of keys
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], [])
>>> dict1
{'c': [], 'b': [], 'a': []}
this can be a handy function.
here we are assigning to each key a default value which also happens to be an empty list.
# the dict has its own id.
>>> id(dict1)
140150327601160
# but look at the ids of the values.
>>> id(dict1['a'])
140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
Indeed they are all using the same ref!
A change to one is a change to all, since they are in fact the same object!
>>> dict1['a'].append('apples')
>>> dict1
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
>>> id(dict1['a'])
>>> 140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
for many, this was not what was intended!
Now let's try it with making an explicit copy of the list being used as a the default value.
>>> empty_list = []
>>> id(empty_list)
140150324169864
and now create a dict with a copy of empty_list.
>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:])
>>> id(dict2)
140150323831432
>>> id(dict2['a'])
140150327184328
>>> id(dict2['b'])
140150327184328
>>> id(dict2['c'])
140150327184328
>>> dict2['a'].append('apples')
>>> dict2
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
Still no joy!
I hear someone shout, it's because I used an empty list!
>>> not_empty_list = [0]
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:])
>>> dict3
{'c': [0], 'b': [0], 'a': [0]}
>>> dict3['a'].append('apples')
>>> dict3
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']}
The default behavior of fromkeys() is to assign None to the value.
>>> dict4 = dict.fromkeys(['a', 'b', 'c'])
>>> dict4
{'c': None, 'b': None, 'a': None}
>>> id(dict4['a'])
9901984
>>> id(dict4['b'])
9901984
>>> id(dict4['c'])
9901984
Indeed, all of the values are the same (and the only!) None.
Now, let's iterate, in one of a myriad number of ways, through the dict and change the value.
>>> for k, _ in dict4.items():
... dict4[k] = []
>>> dict4
{'c': [], 'b': [], 'a': []}
Hmm. Looks the same as before!
>>> id(dict4['a'])
140150318876488
>>> id(dict4['b'])
140150324122824
>>> id(dict4['c'])
140150294277576
>>> dict4['a'].append('apples')
>>> dict4
>>> {'c': [], 'b': [], 'a': ['apples']}
But they are indeed different []s, which was in this case the intended result.
You can use this:
l = ['a', 'b', 'c']
d = dict((k, [0, 0]) for k in l)
You are populating your dictionaries with references to a single list so when you update it, the update is reflected across all the references. Try a dictionary comprehension instead. See
Create a dictionary with list comprehension in Python
d = {k : v for k in blah blah blah}
You could use this:
data[:1] = ['hello']
I have got the below problem.
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
Normal retrieval method: dict1['a'] -> Output - > 1
expected method: dict1['a', 'b'] - > Output - > [1, 2]
My requirement is to extract multiple values from a dictionary by providing multiple keys at the same time as mentioned in the expected method above.
Is there a way to do it? If I have to edit the built-in dict class methods, how do I do it?
You can do what's said in the other answers or use map on your list of keys with the get dictionnary method :
map(dict1.get, ["a", "b"])
Use a list comprehension:
[ dict[k] for k in ('a','b')]
[ dict[k] for k in my_iterable ]
will throw KeyError if any of the keys in the iterable are not in the dict. It may be better to do
[ dict.get(k, my_default_value) for k in my_iterable ]
You can use list comprehension : [dict1[key] for key in ('a', 'b')]
It is equivalent to
output = []
for key in ('a', 'b'):
output.append(dict1[key])
This is one way of doing this through subclassing:
class CustomDict(dict):
def __init__(self, dic):
self.dic = dic
def __getitem__(self, items):
values = []
for item in items:
values.append(self.dic[item])
return values if len(values) > 1 else values[0]
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
new_d = CustomDict(d)
print(new_d['a'])
print(new_d['a', 'b'])
print(new_d['a', 'b', 'c'])
print(new_d['a', 'c', 'd'])
Output:
1
[1, 2]
[1, 2, 3]
[1, 3, 4]
Explanation:
The new_d is an object of the CustomDict class, it will always fall back to the parent class's methods (so that looping over the object and other things you might want to do to a dictionary work) except when one of the overriden methods (init, getitem) get called.
So when one uses new_d['a', 'b'] the overriden __getitem__ method gets called. The overriden method uses the __getitem__ of the self.dic (which is a normal dictionary) to actually access the dictionary values for every key given.
I've been experimenting trying to get this to work and I've exhausted every idea and web search. Nothing seems to do the trick. I need to sum numbers in a defaultdict(list) and i just need the final result but no matter what i do i can only get to the final result by iterating and returning all sums adding up to the final. What I've been trying generally,
d = { key : [1,2,3] }
running_total = 0
#Iterate values
for value in d.itervalues:
#iterate through list inside value
for x in value:
running_total += x
print running_total
The result is :
1,3,6
I understand its doing this because its iterating through the for loop. What i dont get is how else can i get to each of these list values without using a loop? Or is there some sort of method iv'e overlooked?
To be clear i just want the final number returned e.g. 6
EDIT I neglected a huge factor , the items in the list are timedealta objects so i have to use .seconds to make them into integers for adding. The solutions below make sense and I've tried similar but trying to throw in the .seconds conversion in the sum statement throws an error.
d = { key : [timedelta_Obj1,timedelta_Obj2,timedelta_Obj3] }
I think this will work for you:
sum(td.seconds for sublist in d.itervalues() for td in sublist)
Try this approach:
from datetime import timedelta as TD
d = {'foo' : [TD(seconds=1), TD(seconds=2), TD(seconds=3)],
'bar' : [TD(seconds=4), TD(seconds=5), TD(seconds=6), TD(seconds=7)],
'baz' : [TD(seconds=8)]}
print sum(sum(td.seconds for td in values) for values in d.itervalues())
You could just sum each of the lists in the dictionary, then take one final sum of the returned list.
>>> d = {'foo' : [1,2,3], 'bar' : [4,5,6,7], 'foobar' : [10]}
# sum each value in the dictionary
>>> [sum(d[i]) for i in d]
[10, 6, 22]
# sum each of the sums in the list
>>> sum([sum(d[i]) for i in d])
38
If you don't want to iterate or to use comprehensions you can use this:
d = {'1': [1, 2, 3], '2': [3, 4, 5], '3': [5], '4': [6, 7]}
print(sum(map(sum, d.values())))
If you use Python 2 and your dict has a lot of keys it's better you use imap (from itertools) and itervalues
from itertools import imap
print sum(imap(sum, d.itervalues()))
Your question was how to get the value "without using a loop". Well, you can't. But there is one thing you can do: use the high performance itertools.
If you use chain you won't have an explicit loop in your code. chain manages that for you.
>>> data = {'a': [1, 2, 3], 'b': [10, 20], 'c': [100]}
>>> import itertools
>>> sum(itertools.chain.from_iterable(data.itervalues()))
136
If you have timedelta objects you can use the same recipe.
>>> data = {'a': [timedelta(minutes=1),
timedelta(minutes=2),
timedelta(minutes=3)],
'b': [timedelta(minutes=10),
timedelta(minutes=20)],
'c': [timedelta(minutes=100)]}
>>> sum(td.seconds for td in itertools.chain.from_iterable(data.itervalues()))
8160
I am doing a boolean retrieval project, the first phase is indexing. I am trying to build an inverted index now. Say I got a sorted list like following: how can I merge the items
list = [('a',1),('a',2),('a',3),('b',1),('b',2),('b',3)...]
such that I can get a dictionary like the following and it remains sorted:
dict = {'a':[1,2,3], 'b':[1,2,3]...}, thx a lot
You can do it like this:
>>> import collections
>>> mylist = [('a',1),('a',2),('a',3),('b',1),('b',2),('b',3)]
>>> result = collections.defaultdict(list)
>>> for item in mylist:
result[item[0]].append(item[1])
>>> dict(result)
{'a': [1, 2, 3], 'b': [1, 2, 3]}
defaultdict(list) creates a dictionary in which keys are initialised upon first access to an object created using the callable passed as the argument (in this case list). It avoids having to check whether the key already exists or not.
The last line converts the defaultdict to a normal dict - it is not strictly necessary as defaultdict behaves like a normal dictionary too.
Values are appended to each key in the same order as the original list. However, the keys themselves will not be ordered (this is a property of dictionaries).
Update: if you need the dictionary keys to remain sorted as well, you can do this:
>>> import collections
>>> mylist = [('a',1),('a',2),('c',1),('c',2),('b',1),('b',2)]
>>> result = collections.OrderedDict()
>>> for item in mylist:
if item[0] not in result:
result[item[0]] = list()
result[item[0]].append(item[1])
>>> result
OrderedDict([('a', [1, 2]), ('c', [1, 2]), ('b', [1, 2])])
>>> result.keys()
['a', 'c', 'b']
Obviously, you cannot use dict(result) in this case as dict does not maintain any specific key order.
I'm supposed to program in Python, and I've only used Python for 3 weeks. I have to solve all kinds of problems and write functions as training. For one of my functions I use this line.
theDict = dict( [(k,v) for k,v in theDict.items() if len(v)>0])
However I can't use anything I don't fully understand or can't fully explain. I understand the gist of the line, but, I can't really explain it. So my instructor told me that to use this, i must learn ether everything about tuples and fully understand list comprehension, or i must write that in pure python.
The line basically looks into a dictionary, and inside the dictionary, its supposed to look for values that are equal to empty lists and delete those keys/values.
So, my question is, what would this line look like in pure, non list comprehension python?
I'll attempt to write it because I want to try my best, and this isn't a website where you get free answers, but you guys correct me and help me finish it if it doesn't work.
Also another problem is that, the empty lists inside the 'value' of the dictionary, if they are empty, then they won't be processed inside the loop. The loop is supposed to delete the key that is equal to the empty value. So how are you supposed to check if the list is empty, if the check is inside the loop, and the loop won't have the empty array in its body?
for key,value in TheDict.items(): #i need to add 'if value:' somewhere,
#but i don't know how to add it to make it work, because
#this checks if the value exists or not, but if the value
#doesn't exist, then it won't go though this area, so
#there is no way to see if the value exists or not.
theDict[key]=value
If there is a better method to remove dictionary values that have a value of an empty list. please let me know.
And how will
theDict = dict( [(k,v) for k,v in theDict.items() if len(v)>0])
look like if it didn't use a generator?
result = dict([(k,v) for k,v in theDict.items() if len(v)>0])
will look like(if you want new dictionary)
result = {}
for key, value in theDict.items():
if len(value) > 0:
result[key] = value
if you want to modify existing dictionary:
for key, value in theDict.items():
if not len(value) > 0:
del theDict[key]
if v signifies if v has some value, if v donesn't have any value, control will not enter the condition and skip the value
In [25]: theDict={'1':'2','3':'', '4':[]}
In [26]: for k,v in theDict.items():
....: if v:
....: newDict[k]=v
....:
In [27]: newDict
Out[27]: {'1': '2'}
==========================
In [2]: theDict = { 1: ['e', 'f'], 2: ['a', 'b', 'c'], 4: ['d', ' '], 5: [] }
In [3]: newDict = {}
In [4]: for k,v in theDict.items():
...: if v:
...: newDict[k]=v
...:
In [5]: newDict
Out[5]: {1: ['e', 'f'], 2: ['a', 'b', 'c'], 4: ['d', ' ']}
Updated the answer as per your input...
Just for fun:
from operator import itemgetter
theDict = dict(filter(itemgetter(1), theDict.items()))
To remove an element from a dictionary, you can use the del keyword:
>>> d = {1: 2, 3: 4}
>>> d
{1: 2, 3: 4}
>>> del d[1]
>>> d
{3: 4}
>>>
This will probably be more efficient than generating a completely new dictionary. Then, you can use a similar structure to above:
for k in theDict:
if len(theDict[k]) == 0:
del theDict[k]
Does that make sense?
theDict = dict( [(k,v) for k,v in theDict.items() if len(v)>0])
However I can't use anything I don't fully understand or can't fully explain. I understand the gist of the line, but, I can't really explain it.
Background
The easiest way to understand or demo behaviour in python is using the interactive interpreter:
python -i
In the interactive interpreter there are two fabulously useful commands:
dir - takes an optional argument of an object, returns a list of the attributes on the object.
help - accesses inline documentation
You can use dir to find out, for example what methods an object has and then look at their documentation using help.
Explaining the line in question
Here's a sample dictionary:
>>> theDict = dict(a=[1,2],b=[3,4],c=[])
>>> theDict
{'a': [1, 2], 'c': [], 'b': [3, 4]}
The list comprehension returns a list of key-value pairs as tuples:
>>> [(k,v) for k,v in theDict.items()]
[('a', [1, 2]), ('c', []), ('b', [3, 4])]
The if statement filters the resulting list.
>>> [(k,v) for k,v in theDict.items() if len(v) > 0]
[('a', [1, 2]), ('b', [3, 4])]
The dict can be instantiated with a sequence of key-value pairs:
>>> dict([(k,v) for k,v in theDict.items() if len(v) > 0])
{'a': [1, 2], 'b': [3, 4]}
Putting it all together:
>>> theDict = dict(a=[1,2],b=[3,4],c=[])
>>> theDict
{'a': [1, 2], 'c': [], 'b': [3, 4]}
>>> theDict = dict([(k,v) for k,v in theDict.items() if len(v) > 0])
>>> theDict
{'a': [1, 2], 'b': [3, 4]}
The original dict object is replaced with a new one instantiated using the list comprehension filtered list of it's key-value pairs.
If you follow all this (and play with it yourself in the interactive interpreter) you will understand what's going on in this line of code you've asked about.
What you probably want is a defaultdict with a list as the empty value.
Here's your function in a more or less readable way:
def clean_whitespace(dct):
out = {}
for key, val in dct.items():
val = map(str.strip, val)
val = filter(None, val)
if val:
out[key] = val
return out
or, using comprehensions,
def clean_whitespace(dct):
out = {}
for key, val in dct.items():
val = [x.strip() for x in val]
val = [x for x in val if x]
if val:
out[key] = val
return out
Let us know if you need comments or explanations.
the solution was under my nose. sorry guys. thank you for all your help +1 for everyone
def CleanWhiteSpace(theDict) :
for k,v in theDict.items():
if not v:
del theDict[k]
return theDict