I'm a Python Newb and trying to create a dictionary with ordered values.
Since dict.fromkeys only allows me to copy the same value for each key, I've set all values to 0 and tried something like this:
def Ord_Values_in_Dic(D):
c = 0
for value in D.values():
c += 1
value += c
return D
My output only changes the first value of the dictionary to 1 though, instead I'd want the second value to also change to 2, the third value to change to 3 and so on...
I don't get if the loop isn't iterating correctly through the dictionary or there's something else wrong.
Since dict.fromkeys only allows me to copy the same value for each key
then it is not right tool for you task. You might use zip to prepare dict from 2 iterables - one for keys, one for values, consider following simple example
keys = ["x","y","z"]
d = dict(zip(keys,range(3)))
print(d) # {'x': 0, 'y': 1, 'z': 2}
range with single arguments gives subsequent numbers from 0 (inclusive) to given value (exclusive), so in above example: 0,1,2
Got it!
import numpy as np
a = np.linspace(0,100,100)
b = np.sin(a)
c = np.cos(a)
idx = list(range(1,101))
X = dict(zip(b, idx))
Y = dict(zip(c, idx))
This solved it!
Thank you :)
Related
I'm trying to generate a dictionary where value is a list using following dictionary of comprehension method.
>>> x = ['a','b','c']
>>> y = {'a':1,'b':2}
>>> z = {i:[].append(j) for (i,j) in y.items() if i in x and j < 2}
>>> z
{'a': None}
I'm trying to get:
{'a':[1]}
Can someone please let me know how to do that? I think I'm getting None as value as it is acting as function and returning None.
Code
x = ['a','b','c']
y = {'a':1,'b':2}
z = {key: [y[key]] for key in list(y.keys()) if key in x and y[key] < 2}
print(z)
output:
{'a': [1]}
Explaination
i get every key from y with list(y.keys())
if they key is in x i continue else i skip to next key
if above condition is satisfied i control if the key value in y is smalller than 2
if also the above condition is satisfied i create a new item in z with key as key and a list containing y value as value
the error rin your code was just that [].append(j) returned None so you only ad to do:
z = {i:[j] for (i,j) in y.items() if i in x and j < 2}
another weird thing is to create a list for j that is a single value, but, becaouse you required it in your expected output and you have surely your reasons to do that, i keeped the output as you wanted, but in general if it is a single value is better to store it directly in the dictand not create a nested list for it in a dict
When the keys in a dictionary comprehension is the same, I want their values to be added up. For example,
>>> dct = {-1: 1, 0: 2, 1: 3}
>>> {k**2: v for k, v in dct.items()}
{1: 3, 0: 2}
However, what I want to get in this case is {1: 4, 0: 2}, because both the square of 1 and -1 is 1, and 1 + 3 = 4.
Clearly, I can do it with a for loop, but is there a shorthand?
There isn't a shorthand version, since your comprehension would need to keep track of the current state which isn't doable. Like you said, the answer is a for loop:
old = {-1: 1, 0: 2, 1:3}
new = {}
for k, v in old.items():
new[k**2] = new.get(k**2, 0) + v
The trick using the dict.get method I saw somewhere in the Python docs. It does the same thing as:
if k**2 in new:
new[k**2] += v
else:
new[k**2] = v
But this variation uses the get method which returns a default 0 which is added on to the value that will be assigned (when the key doesn't exist). Since it is 0, and the values are numbers being added, 0 has no effect. By contrast, if you needed to get the product, you'd use 1 as the default as starting off with 0 will mean that you never increase the value.
In addition, the latter, more verbose, method shown above evaluates k**2 twice each cycle which uses up computation. To make it use 1 calculation would require another line of code which in my opinion isn't worth the time when the get method is so much cleaner.
One of the fastest ways to calculate the sums is to use defaultdict - a self-initializing dictionary:
from collections import defaultdict
new = defaultdict(int)
for k, v in old.items():
new[k**2] += v
I have the following dictionary, where keys are integers and values are floats:
foo = {1:0.001,2:2.097,3:1.093,4:5.246}
This dictionary has keys 1, 2, 3 and 4.
Now, I remove the key '2':
foo = {1:0.001,3:1.093,4:5.246}
I only have the keys 1, 3 and 4 left. But I want these keys to be called 1, 2 and 3.
The function 'enumerate' allows me to get the list [1,2,3]:
some_list = []
for k,v in foo.items():
some_list.append(k)
num_list = list(enumerate(some_list, start=1))
Next, I try to populate the dictionary with these new keys and the old values:
new_foo = {}
for i in num_list:
for value in foo.itervalues():
new_foo[i[0]] = value
However, new_foo now contains the following values:
{1: 5.246, 2: 5.246, 3: 5.246}
So every value was replaced by the last value of 'foo'. I think the problem comes from the design of my for loop, but I don't know how to solve this. Any tips?
Using the list-comprehension-like style:
bar = dict( (k,v) for k,v in enumerate(foo.values(), start=1) )
But, as mentioned in the comments the ordering is going to be arbitrary, since the dict structure in python is unordered. To preserve the original order the following can be used:
bar = dict( ( i,foo[k] ) for i, k in enumerate(sorted(foo), start=1) )
here sorted(foo) returns the list of sorted keys of foo. i is the new enumeration of the sorted keys as well as the new enumeration for the new dict.
Like others have said, it would be best to use a list instead of dict. However, in case you prefer to stick with a dict, you can do
foo = {j+1:foo[k] for j,k in enumerate(sorted(foo))}
Agreeing with the other responses that a list implements the behavior you describe, and so it probably more appropriate, but I will suggest an answer anyway.
The problem with your code is the way you are using the data structures. Simply enumerate the items left in the dictionary:
new_foo = {}
for key, (old_key, value) in enumerate( sorted( foo.items() ) ):
key = key+1 # adjust for 1-based
new_foo[key] = value
A dictionary is the wrong structure here. Use a list; lists map contiguous integers to values, after all.
Either adjust your code to start at 0 rather than 1, or include a padding value at index 0:
foo = [None, 0.001, 2.097, 1.093, 5.246]
Deleting the 2 'key' is then as simple as:
del foo[2]
giving you automatic renumbering of the rest of your 'keys'.
This looks suspiciously like Something You Should Not Do, but I'll assume for a moment that you're simplifying the process for an MCVE rather than actually trying to name your dict keys 1, 2, 3, 4, 5, ....
d = {1:0.001, 2:2.097, 3:1.093, 4:5.246}
del d[2]
# d == {1:0.001, 3:1.093, 4:5.246}
new_d = {idx:val for idx,val in zip(range(1,len(d)+1),
(v for _,v in sorted(d.items())))}
# new_d == {1: 0.001, 2: 1.093, 3: 5.246}
You can convert dict to list, remove specific element, then convert list to dict. Sorry, it is not a one liner.
In [1]: foo = {1:0.001,2:2.097,3:1.093,4:5.246}
In [2]: l=foo.values() #[0.001, 2.097, 1.093, 5.246]
In [3]: l.pop(1) #returns 2.097, not the list
In [4]: dict(enumerate(l,1))
Out[4]: {1: 0.001, 2: 1.093, 3: 5.246}
Try:
foo = {1:0.001,2:2.097,3:1.093,4:5.246}
foo.pop(2)
new_foo = {i: value for i, (_, value) in enumerate(sorted(foo.items()), start=1)}
print new_foo
However, I'd advise you to use a normal list instead, which is designed exactly for fast lookup of gapless, numeric keys:
foo = [0.001, 2.097, 1.093, 5.245]
foo.pop(1) # list indices start at 0
print foo
One liner that filters a sequence, then re-enumerates and constructs a dict.
In [1]: foo = {1:0.001, 2:2.097, 3:1.093, 4:5.246}
In [2]: selected=1
In [3]: { k:v for k,v in enumerate((foo[i] for i in foo if i<>selected), 1) }
Out[3]: {1: 2.097, 2: 1.093, 3: 5.246}
I have a more compact method.
I think it's more readable and easy to understand. You can refer as below:
foo = {1:0.001,2:2.097,3:1.093,4:5.246}
del foo[2]
foo.update({k:foo[4] for k in foo.iterkeys()})
print foo
So you can get answer you want.
{1: 5.246, 3: 5.246, 4: 5.246}
I have a dictionary of a list of dictionaries. something like below:
x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
The length of the lists (values) is the same for all keys of dict x.
I want to get the length of any one value i.e. a list without having to go through the obvious method -> get the keys, use len(x[keys[0]]) to get the length.
my code for this as of now:
val = None
for key in x.keys():
val = x[key]
break
#break after the first iteration as the length of the lists is the same for any key
try:
what_i_Want = len(val)
except TypeError:
print 'val wasn't set'
i am not happy with this, can be made more 'pythonic' i believe.
This is most efficient way, since we don't create any intermediate lists.
print len(x[next(iter(x))]) # 2
Note: For this method to work, the dictionary should have atleast one key in it.
What about this:
val = x[x.keys()[0]]
or alternatively:
val = x.values()[0]
and then your answer is
len(val)
Some of the other solutions (posted by thefourtheye and gnibbler) are better because they are not creating an intermediate list. I added this response merely as an easy to remember and obvious option, not a solution for time-efficient usage.
Works ok in Python2 or Python3
>>> x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
>>> next(len(i) for i in x.values())
2
This is better for Python2 as it avoids making a list of the values. Works well in Python3 too
>>> next(len(x[k]) for k in x)
2
Using next and iter:
>>> x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
>>> val = next(iter(x.values()), None) # Use `itervalues` in Python 2.x
>>> val
[{'q': 2, 'p': 1}, {'q': 5, 'p': 4}]
>>> len(val)
2
>>> x = {}
>>> val = next(iter(x.values()), None) # `None`: default value
>>> val is None
True
>>> x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
>>> len(x.values()[0])
2
Here, x.values gives you a list of all values then you can get length of any one value from it.
Is it possible to replace all values in a dictionary, regardless of value, with the integer 1?
Thank you!
Sure, you can do something like:
d = {x: 1 for x in d}
That creates a new dictionary d that maps every key in d (the old one) to 1.
You can use a dict comprehension (as others have said) to create a new dictionary with the same keys as the old dictionary, or, if you need to do the whole thing in place:
for k in d:
d[k] = 1
If you're really fond of 1-liners, you can do it in place using update:
d.update( (k,1) for k in d )
a = {1:2, 2:2,3:2}
a = {x:1 for (x,_) in a.iteritems()}
print a
{1: 1, 2: 1, 3: 1}
Yes, it's possible. Iterate through every key in the dictionary and set the related value to 1.