Set dictionary values based on range - python

index = {
u'when_air': 0,
u'chrono': 1,
u'age_marker': 2,
u'name': 3
}
How can I make this more beautiful (and clear) way than just manually setting each value?
like:
index = dict_from_range(
[u'when_air', u'chrono', u'age_marker', u'name'],
range(4)
)

You can feed the results of zip() to the builtin dict():
>>> names = [u'when_air', u'chrono', u'age_marker', u'name']
>>> print(dict(zip(names, range(4))))
{'chrono': 1, 'name': 3, 'age_marker': 2, 'when_air': 0}
zip() will return a list of tuples, where each tuple is the ith element from names and range(4). dict() knows how to create a dictionary from that.
Notice that if you give sequences of uneven lengths to zip(), the results are truncated. Thus it might be smart to use range(len(names)) as the argument, to guarantee an equal length.
>>> print(dict(zip(names, range(len(names)))))
{'chrono': 1, 'name': 3, 'age_marker': 2, 'when_air': 0}

You can use a dict comprehension together with the built-in function enumerate to build the dictionary from the keys in the desired order.
Example:
keys = [u'when_air', u'chrono', u'age_marker', u'name']
d = {k: i for i,k in enumerate(keys)}
print d
The output is:
{u'age_marker': 2, u'when_air': 0, u'name': 3, u'chrono': 1}
Note that with Python 3.4 the enum module was added. It may provide the desired semantics more conveniently than a dictionary.
For reference:
http://legacy.python.org/dev/peps/pep-0274/
https://docs.python.org/2/library/functions.html#enumerate
https://docs.python.org/3/library/enum.html

index = {k:v for k,v in zip(['when_air','chrono','age_marker','name'],range(4))}

This?
#keys = [u'when_air', u'chrono', u'age_marker', u'name']
from itertools import count
print dict(zip(keys, count()))

Related

Can't crate a dictionary from two lists using dictionary comprehension with two FORs. Why?

I know that there are a bunch of ways to make a dictionary out of two lists, but I wanted to do it using two FOR loops to iterate over both lists. Therefore, I used the following code. Surprisingly, the code doesn't iterate over the second list that contains the values of the dictionary keys and only considers the last element of the list as the value.
key = ['hello', 'mello', 'vello']
value = [1, 2, 3]
dictionary = {k: v for k in key for v in value}
print('dictionary is ', dictionary)
the result was:
dictionary is: {'hello': 3, 'mello': 3, 'vello': 3}
But I expect that the result would be:
dictionary is: {'hello': 1, 'mello': 2, 'vello': 3}
I appreciate it if anyone can clarify this for me.
My understanding is the full dictionary is being recreated each loop with each number as the key, resulting in only your final output being that of the last value (best shown by reversing your key and value statements, returning {1: 'vello', 2: 'vello', 3: 'vello', 4: 'vello'}
If the other is your intended output, this should work fine:
dictionary = dict(zip(key,value))
You can use zip for this purpose.
dictionary = dict(zip(keys, values))

Sorting arrays within a dictionary

The information inside the arrays is in the "reverse" order of how I want it. Ideally it could be sorted by the dates within the array but I'm 100% certain just reversing the order would work.
By using something like this:
sorted(Dictionary[self], key=lambda i: i[1][0], reverse=True)
I know that the above JUST sorts the arrays themselves into reverse order and not the data inside the array into reverse order.
With the Dictionary like this (all items are a file name)
Dictionary = {'a':[XPJulianDay(Timefurthestinpastfromnow), ... XPJulianDay(timeclosest2currnttime)], 'b':[RQJulianDay(Timefurthestinpastfromnow), ... RQJulianDay(timeclosest2currnttime)], 'c':[WSJulianDay(Timefurthestinpastfromnow), ... WSJulianDay(timeclosest2currnttime)] ..... (9 different ones total) }
turning into this
Dictionary = {'a':[XPJulianDay(timeclosest2currnttime), ... XPJulianDay(Timefurthestinpastfromnow)], 'b':[RQJulianDay(timeclosest2currnttime), ... RQJulianDay(Timefurthestinpastfromnow)], 'c':[WSJulianDay(timeclosest2currnttime), ... WSJulianDay(Timefurthestinpastfromnow)] .... }
You can try that:
Dictionary.update({ k: sorted(v) for k, v in Dictionary.items() })
It updates the dictionary with its own keys, with sorted values.
Example:
>>> Dictionary = {"a": [7,6,1,2], "b": [8,0,2,5] }
>>> Dictionary.update({ k: sorted(v) for k, v in Dictionary.items() })
>>> Dictionary
{'a': [1, 2, 6, 7], 'b': [0, 2, 5, 8]}
>>>
Note that a new dictionary is created for the call to .update() using a dict comprehension.
If needed you can replace sorted() by reversed() ; but reversed() returns an iterator so if you want a list you need to call it with list() (it is better to keep the iterator if you can).
Example with reversed:
>>> Dictionary = {"a": [7,6,1,2], "b": [8,0,2,5] } ; Dictionary.update({ k: reversed(v) for k, v in Dictionary.items() })
>>> Dictionary
{'a': <list_reverseiterator object at 0x7f537a0b3a10>, 'b': <list_reverseiterator object at 0x7f537a0b39d0>}
>>>
You can use the dict comprehension as stated by #mguijarr or use dict and zip
Dictionary = dict(zip(Dictionary, map(sorted, Dictionary.values()))))
But if your keys really are just the 'a', 'b', ... then why are you using a dict? Just use a list...

Python: Extract all values in a dictionary into assignment statements?

For a dictionary
d={'foo1': 1, 'foo2': 2, 'foo3': 3}, what is the most efficient way to assign the strings to their definitions:
foo1=1
foo2=2
foo3=3
When no assignment statements are used, I need to call the entry with the dictionary, eg. d['foo1'], but I don't plan to use this.
Note: Thanks for pointing out that it was a string. However, I am now assigning the string terms to their corresponding values in the dictionary.
d = {'a': 1, 'b': 2}
locals().update(d)
>>> globals()['test'] = 10
>>> test
10
Not the most pretty way, but it works.
d = {'foo1': 1, 'foo2': 2, 'foo3': 3}
for key, val in d.items():
globals()[key] = val
print(foo1)
(Or use locals(), but Colin beat me to it)

Summing up numbers in a defaultdict(list)

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

How to convert Counter object to dict?

Data frame:
pair = collections.defaultdict(collections.Counter)
e.g.
pair = {'doc1': {'word1':4, 'word2':3},
'doc2': {'word1':2, 'word3':4},
'doc3': {'word2':2, 'word4':1},
...}
I want to keep the data frame but alter the type of this part {'word1':4, 'word2':3} {'word1':2, 'word3':4}``... It is now a Counter and I need a dict.
I tried this to get the data from pair, but I do not know how to create a dict for each doc:
new_pair = collections.defaultdict(collections.Counter)
for doc, tab in testing.form.items():
for word, freq in tab.items():
new_pair[doc][word] = freq
I do not want to change the output. I just need that in each doc, the data type is dict, not Counter.
A Counter is already a dict - or, a subclass of it. But, if you really need exactly a dict for some reason, then its a one-liner:
>>> c = Counter(word1=4, word2=3)
>>> c
Counter({'word1': 4, 'word2': 3})
>>> dict(c)
{'word1': 4, 'word2': 3}
Any Mapping (anything that behaves like a dictionary) can be passed into dict, and you will get a dict with the same contents. There is no need to iterate over it to construct it yourself.
This gives you one loop, with one line in the body instead of a nested loop. But any code of the form:
thing = a new empty collection
for elem in old_thing:
Add something to do with elem to thing
Can usually be done in one line using a generator expression or a list, set or dict comprehension. We're building a dict, so a dict comprehension (the Examples section is what you're most interested in) seems likely. I'll leave coming up with it as an exercise for the reader. ;-)
Since Counter is already a dict.
I would like to suggest this in addition to #lvc answer as well.
>>> c = Counter(word1=4, word2=3)
>>> c
Counter({'word1': 4, 'word2': 3})
>>> isinstance(c,dict)
True
>>> {**c}
{'word1': 4, 'word2': 3}
This allows you to add more key and combine multiple dict or counter
>>> {**c, 'total': sum(c.values())}
{'word1': 4, 'word2': 3, 'total': 7}
Maybe you are looking for:
>>> from collections import defaultdict
>>> pair = defaultdict(dict)
>>> pair[3][2]='hello'
>>>
>>> pair
defaultdict(<type 'dict'>, {3: {2: 'hello'}})
>>>
>>> pair[3]
{2: 'hello'}
>>>
new_pair = {} # simple dict at the top level
for doc, tab in testing.form.items():
for word, freq in tab.items():
# top-level values is word counters
new_pair[doc].setdefault(word, Counter()) += freq
The Counter is also a dict. But depend on you need, maybe the follow code is you want.
new_pair ={}
for doc, tab in pari.items():
new_pair[doc] = {}
for word, freq in tab.items():
new_pair[doc][word] = freq
the new_pair dict is you want. Good Luck!

Categories

Resources