how to convert dict_values into a set - python-3.x

I have a dict that contains sets as values for each key, e.g.
{'key1': {8772, 9605},'key2': {10867, 10911, 10917},'key3': {11749,11750},'key4': {14721, 19755, 21281}}
Now I want to put each value, i.e. set of ints into a set, I am wondering what is the best way/most efficient way to do this.
{8772,9605,10867,10911,10917,11749,11750,14721,19755,21281}
I tried to retrieve the values from the dict using dict.values(), but that returns a dict_values object, making it a list, list(dict.values()) gave me a list of sets, set(list(exact_dups.values())) threw me errors,
TypeError: unhashable type: 'set'
UPDATE. forgot to mention the result set also need to maintain uniqueness, i.e. no duplicates.

You can do it with set.union() and unpacked values:
set.union(*my_dict.values())
Or you can combine set.union() with reduce:
reduce(set.union, my_dict.values())

Use a combination of reduce and set union:
from functools import reduce
result = reduce(lambda a, b: a.union(b), my_dict.values(), set())
print(result)

A sequence reduction with the set union operator (|, "or") will do:
from functools import reduce
from operator import or_
d = {'key1': {8772, 9605},'key2': {10867, 10911, 10917},'key3': {11749,11750},'key4': {14721, 19755, 21281}}
s = reduce(or_, d.values())
It essentially does d['key1'] | d['key2'] | ....

Very simple, readable, self-explanatory solution without any imports:
arr = []
for key in dictionary:
arr += list(dictionary[key])
answer = set(arr.sorted())

A simpler way
set1 = set()
for i in dict.values():
set1.update(i)
set1

You can try this way:
keys_set= set()
for item in dict.values():
keys_set.add(item)

We can access only values as that's what OP wants and then sort it as follows :
dict1 = {'key1': {8772, 9605},'key2': {10867, 10911, 10917},'key3': {11749,11750},'key4': {14721, 19755, 21281}}
arr = []
for key in sorted(dict1.values()):
arr += key
print('{', ','.join(str(n) for n in arr), '}', sep='')
produces,
{8772,9605,10867,10917,10911,11749,11750,14721,19755,21281}
[Program finished]
as requested by OP.

Related

Iterate through dictionary by indexes

How to bypass python out of box mechanism when an order of items() in the loop does not correspond to the order it supposes to be?
st = 'Tree'
freq = Counter(st)
sorted(freq.items(), key=lambda item: item[1])
arr = []
for k, v in freq.items():
for i in range(v):
arr.append(k)
I expect to get in the first iteration pair: ('e', 2), but instead it is ('t', 1).
But sorting was applied to dictionary at row 3.
How to iterate dictionary in way it is sorted? (without applying underhood re-order)
UPD. The question has already been answered, however, will be good to know why dictionaries implemented in Python3 in that way.
sort by keys:
a = dict(b=3, c=5, a=10)
for k in sorted(a):
print(f"{k}: {a[k]}")
and if you want to sort them by the values:
a = dict(b=3, c=5, a=10)
for k, v in sorted(a.items(), key=lambda item: item[1]):
print(f"{k}: {a[k]}")

Convert elements in ONE list to keys and values in a dictionary

I'm looking for a way to convert a list to a dictionary as shown below. Is this possible? Thanks in advance.
list = ["1/a", "2/b", "3/c"]
dict = {"1": "a", "2": "b", "3": "c"}
Of course it is possible.
First, you can split an element of the list with e.split("/"), which will give a list for example splitted = ["1", "a"].
You can assign the first element to the key and the second to the value:
k = splitted[0]
v = splitted[1]
or another way to express that:
k,v = splitted
Then you can iterate over your list to build your dict, so if we wrap this up (you should not call a list list because list is a type and an already existing identifier:
d = {}
for e in elements:
k,v = e.split("/")
d[k] = v
You can also do that in one line with a dict comprehension:
d = {k:v for k,v in [e.split("/") for e in elements]}
Yes you can.
If you want to have everything after the '/' (i.e. 2nd char), you can do:
dict = {c[0]:c[2:] for c in list}
If you want to have everything after the '/' (but may not be the 2nd char), you can do:
dict = {c[0]:c.split('/')[1] for c in list}
It really dependes on the input you have and what output you want
You can do like this.
lista = ["1/a", "2/b", "3/c"]
new_dict = {}
for val in lista:
new_dict.update({val[0]:val[2]})
print(new_dict)
Try this
list = ["1as/aasc", "2sa/bef", "3edc/cadeef"]
dict = {i.split('/')[0]:i.split('/')[1] for i in list}
Answer will be
{'1as': 'aasc', '2sa': 'bef', '3edc': 'cadeef'}
I have given a different test case. Hope this will answer your question.

How to get the innermost value among dictionaries at one go?

Here is my dictionary:
my_dict = {'00.Life': help}
help ={'A.Death':['dying','dead','mourir','pass away']}
I have one dictionary inside the other one.
How to get the innermost value at one go?
I hope I could just input 'dying'(one of the elements in the list) to get ['dying','dead','mourir','pass away'] list.
How to do that?
You can't do it "at one go" using your existing data structure. You will have to either iterate all the values, or construct a reversed, lookup dictionary first. For example:
>>> my_help ={'A.Death':['dying','dead','mourir','pass away']}
>>> my_dict = {'00.Life': my_help}
>>> lookup_dict = {k: v for v in my_dict["00.Life"].values() for k in v}
>>> lookup_dict["dying"]
['dying', 'dead', 'mourir', 'pass away']

Get name of elements of a OrderedDict in pandas [duplicate]

With Python 2.7, I can get dictionary keys, values, or items as a list:
>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]
With Python >= 3.3, I get:
>>> newdict.keys()
dict_keys([1, 2, 3])
How do I get a plain list of keys with Python 3?
This will convert the dict_keys object to a list:
list(newdict.keys())
On the other hand, you should ask yourself whether or not it matters. It is Pythonic to assume duck typing -- if it looks like a duck and it quacks like a duck, it is a duck. The dict_keys object can be iterated over just like a list. For instance:
for key in newdict.keys():
print(key)
Note that dict_keys doesn't support insertion newdict[k] = v, though you may not need it.
Python >= 3.5 alternative: unpack into a list literal [*newdict]
New unpacking generalizations (PEP 448) were introduced with Python 3.5 allowing you to now easily do:
>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]
Unpacking with * works with any object that is iterable and, since dictionaries return their keys when iterated through, you can easily create a list by using it within a list literal.
Adding .keys() i.e [*newdict.keys()] might help in making your intent a bit more explicit though it will cost you a function look-up and invocation. (which, in all honesty, isn't something you should really be worried about).
The *iterable syntax is similar to doing list(iterable) and its behaviour was initially documented in the Calls section of the Python Reference manual. With PEP 448 the restriction on where *iterable could appear was loosened allowing it to also be placed in list, set and tuple literals, the reference manual on Expression lists was also updated to state this.
Though equivalent to list(newdict) with the difference that it's faster (at least for small dictionaries) because no function call is actually performed:
%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop
%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop
%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop
with larger dictionaries the speed is pretty much the same (the overhead of iterating through a large collection trumps the small cost of a function call).
In a similar fashion, you can create tuples and sets of dictionary keys:
>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}
beware of the trailing comma in the tuple case!
list(newdict) works in both Python 2 and Python 3, providing a simple list of the keys in newdict. keys() isn't necessary.
You can also use a list comprehension:
>>> newdict = {1:0, 2:0, 3:0}
>>> [k for k in newdict.keys()]
[1, 2, 3]
Or, shorter,
>>> [k for k in newdict]
[1, 2, 3]
Note: Order is not guaranteed on versions under 3.7 (ordering is still only an implementation detail with CPython 3.6).
A bit off on the "duck typing" definition -- dict.keys() returns an iterable object, not a list-like object. It will work anywhere an iterable will work -- not any place a list will. a list is also an iterable, but an iterable is NOT a list (or sequence...)
In real use-cases, the most common thing to do with the keys in a dict is to iterate through them, so this makes sense. And if you do need them as a list you can call list().
Very similarly for zip() -- in the vast majority of cases, it is iterated through -- why create an entire new list of tuples just to iterate through it and then throw it away again?
This is part of a large trend in python to use more iterators (and generators), rather than copies of lists all over the place.
dict.keys() should work with comprehensions, though -- check carefully for typos or something... it works fine for me:
>>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
>>> [key.split(", ") for key in d.keys()]
[['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]
If you need to store the keys separately, here's a solution that requires less typing than every other solution presented thus far, using Extended Iterable Unpacking (Python3.x+):
newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict
k
# [1, 2, 3]
Operation
no. Of characters
k = list(d)
9 characters (excluding whitespace)
k = [*d]
6 characters
*k, = d
5 characters
Converting to a list without using the keys method makes it more readable:
list(newdict)
and, when looping through dictionaries, there's no need for keys():
for key in newdict:
print key
unless you are modifying it within the loop which would require a list of keys created beforehand:
for key in list(newdict):
del newdict[key]
On Python 2 there is a marginal performance gain using keys().
Yes, There is a better and simplest way to do this in python3.X
use inbuild list() function
#Devil
newdict = {1:0, 2:0, 3:0}
key_list = list(newdict)
print(key_list)
#[1, 2, 3]
I can think of 2 ways in which we can extract the keys from the dictionary.
Method 1: -
To get the keys using .keys() method and then convert it to list.
some_dict = {1: 'one', 2: 'two', 3: 'three'}
list_of_keys = list(some_dict.keys())
print(list_of_keys)
-->[1,2,3]
Method 2: -
To create an empty list and then append keys to the list via a loop.
You can get the values with this loop as well (use .keys() for just keys and .items() for both keys and values extraction)
list_of_keys = []
list_of_values = []
for key,val in some_dict.items():
list_of_keys.append(key)
list_of_values.append(val)
print(list_of_keys)
-->[1,2,3]
print(list_of_values)
-->['one','two','three']
Beyond the classic (and probably more correct) way to do this (some_dict.keys()) there is also a more "cool" and surely more interesting way to do this:
some_dict = { "foo": "bar", "cool": "python!" }
print( [*some_dict] == ["foo", "cool"] ) # True
Note: this solution shouldn't be used in a develop environment; I showed it here just because I thought it was quite interesting from the *-operator-over-dictionary side of view. Also, I'm not sure whether this is a documented feature or not, and its behaviour may change in later versions :)
You can you use simple method like below
keys = newdict.keys()
print(keys)
This is the best way to get key List in one line of code
dict_variable = {1:"a",2:"b",3:"c"}
[key_val for key_val in dict_variable.keys()]

Efficiently Perform Nested Dictionary Lookups and List Appending Using Numpy Nonzero Indices

I have working code to perform a nested dictionary lookup and append results of another lookup to each key's list using the results of numpy's nonzero lookup function. Basically, I need a list of strings appended to a dictionary. These strings and the dictionary's keys are hashed at one point to integers and kept track of using separate dictionaries with the integer hash as the key and the string as the value. I need to look up these hashed values and store the string results in the dictionary. It's confusing so hopefully looking at the code helps. Here's a simplified version of code:
for key in ResultDictionary:
ResultDictionary[key] = []
true_indices = np.nonzero(numpy_array_of_booleans)
for idx in range(0, len(true_indices[0])):
ResultDictionary.get(HashDictA.get(true_indices[0][idx])).append(HashDictB.get(true_indices[1][idx]))
This code works for me, but I am hoping there's a way to improve the efficiency. I am not sure if I'm limited due to the nested lookup. The speed is also dependent on the number of true results returned by the nonzero function. Any thoughts on this? Appreciate any suggestions.
Here are two suggestions:
1) since your hash dicts are keyed with ints it might help to transform them into arrays or even lists for faster lookup if that is an option.
k, v = map(list, (HashDictB.keys(), HashDictB.values())
mxk, mxv = max(k), max(v, key=len)
lookupB = np.empty((mxk+1,), dtype=f'U{mxv}')
lookupB[k] = v
2) you probably can save a number of lookups in ResultDictionary and HashDictA by processing your numpy_array_of_booleans row-wise:
i, j = np.where(numpy_array_of_indices)
bnds, = np.where(np.r_[True, i[:-1] != i[1:], True])
ResultDict = {HashDictA[i[l]]: [HashDictB[jj] for jj in j[l:r]] for l, r in zip(bnds[:-1], bnds[1:])}
2b) if for some reason you need to incrementally add associations you could do something like (I'll shorten variable names for that)
from operator import itemgetter
res = {}
def add_batch(data, res, hA, hB):
i, j = np.where(data)
bnds, = np.where(np.r_[True, i[:-1] != i[1:], True])
for l, r in zip(bnds[:-1], bnds[1:]):
if l+1 == r:
res.setdefault(hA[i[l]], set()).add(hB[j[l]])
else:
res.setdefault(hA[i[l]], set()).update(itemgetter(*j[l:r])(hB))
You can't do much about the dictionary lookups - you have to do those one at a time.
You can clean up the array indexing a bit:
idxes = np.argwhere(numpy_array_of_booleans)
for i,j in idxes:
ResultDictionary.get(HashDictA.get(i)).append(HashDictB.get(j)
argwhere is transpose(nonzero(...)), turning the tuple of arrays into a (n,2) array of index pairs. I don't think this makes a difference in speed, but the code is cleaner.

Resources