How to handle multiple keys for a dictionary in python?
defaultdict
/dict.setdefault
Let's jump into it:
- Iterate over items consecutively
- Append string values belonging to the same key
- Once done, iterate over each key-value pair and join everything together for your final result.
from collections import defaultdict
d = defaultdict(list)
for i, j in zip(list_1, list_2):
d[i].append(j)
The defaultdict
makes things simple, and is efficient with appending. If you don't want to use a defaultdict
, use dict.setdefault
instead (but this is a bit more inefficient):
d = {}
for i, j in zip(list_1, list_2):
d.setdefault(i, []).append(j)
new_dict = {k : ','.join(v) for k, v in d.items()})
print(new_dict)
{'4': 'a', '6': 'b', '8': 'c,d'}
Pandas DataFrame.groupby
+ agg
If you want performance at high volumes, try using pandas:
import pandas as pd
df = pd.DataFrame({'A' : list_1, 'B' : list_2})
new_dict = df.groupby('A').B.agg(','.join).to_dict()
print(new_dict)
{'4': 'a', '6': 'b', '8': 'c,d'}
Creating multiple keys dictionaries from lists
This should give you the result you need using a dictionary comprehension:
Demand_dict = {(p, c): d for p, c, d in zip(Product, Client, Demand)}
It zips the three lists and then iterates over the 3-tuples using the first two values as the key for a dictionary entry and the third value as the value.
Python - create dictionary with multiple keys and where value is also dictionary
you could just do this:
test = {"11.67": 1, "12.67": 2}
res = {key: {"value": str(int(float(key)))} for key in test}
# {'11.67': {'value': '11'}, '12.67': {'value': '12'}}
where i first convert the strings to float
s, then discard the fractional part by using int
and convert back to str
again.
what goes wrong in your code is nicely explained in Carsten's answer.
multiple keys and values in python dictionary
Firstly, you have to be able to get the text output from the app shown in the picture, then you use your dictionary to check it.
And the way to design the dictionary makes it difficult to check. You should design it that way: key is only one string, and values is a list. For example:
Dic = {"A": ["od"], "ab": ["od"], "Acutus": ["Akuten", "Akutna", "Akutno"], "Aromaticus": ["Dišeč", "Odišavljen"]}
So now after you get the text from your app, let's say it is text = 'ab:id'
. You will split it to key and value then check in your dict:
def check(text):
text = text.split(':')
key = text[0]
value = text[1]
if value in Dic[key]:
return True
return False
Let's try it out
>>> check('ab:id')
False
>>> check('ab:od')
True
>>> check('Acutus:Akutna')
True
>>> check('Acutus:Akutno')
True
is there a faster way to get multiple keys from dictionary?
You could use:
>>> list(map(d.get, l))
[1, 2, None]
It has two advantages:
- It performs the
d.get
lookup only once - not each iteration - Only CPython: Because
dict.get
is implemented in C andmap
is implemented in C it can avoid the Python layer in the function call (roughly speaking the details are a bit more complicated).
As for timings (performed on Python 3.6 in a Jupyter notebook):
d = {'a':1, 'b':2, 'c':3, 'd':4}
l = ['a', 'b', 'z']
%timeit list(map(d.get, l))
594 ns ± 41.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [d.get(k) for k in l]
508 ns ± 17.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Note that this is actually slower in this case! That's because for short iterables the map
and list
overhead dominate. So if you want it faster on short iterables stick with your approach.
With longer l
you see that list(map(...))
eventually becomes faster:
d = {'a':1, 'b':2, 'c':3, 'd':4}
l = [random.choice(string.ascii_lowercase) for _ in range(10000)]
%timeit list(map(d.get, l))
663 µs ± 64.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit [d.get(k) for k in l]
1.13 ms ± 7.55 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
However that's still "just" a factor of 2 faster.
Dictionary with multiple keys mapping to same value
Is it what you want to achieve ?
int_dict = { 0 : "String1",
1 : "String2",
2 : "String3",
16 : "String5" };
#range is first inclusive last exlusif, watch out for that
for i in range(3,15) :
int_dict[i] = "String4"
output :
{0: 'String1',
1: 'String2',
2: 'String3',
3: 'String4',
4: 'String4',
5: 'String4',
6: 'String4',
7: 'String4',
8: 'String4',
9: 'String4',
10: 'String4',
11: 'String4',
12: 'String4',
13: 'String4',
14: 'String4',
16: 'String5'}
Edit : you can also use tuple as key
int_dict = { (0,0) : "String1",
(1,1) : "String2",
(2,2) : "String3",
(3,15) :"String4",
(16,16) : "String5"};
def ValueInDict(value):
for i,j in int_dict.items():
if value >= i[0]:
if value <= i[1]:
print(j)
return
print("NOT THERE")
ValueInDict(5)
ouput :
String4
Related Topics
Drop Rows Containing Empty Cells from a Pandas Dataframe
Import Local Module in Jupyter Notebook
How to Decompile a Compiled .Pyc File into a .Py File
How to Create Dynamic Workflows in Airflow
Pyspark Data Frame Converting False and True to 0 and 1
How to Make Tkinter Frames in a Loop and Update Object Values
How to Check for an Exact Word in a String in Python
Finding an Exact Substring in a String in Python
How to Display the Value of the Bar on Each Bar With Pyplot.Barh()
Get All the Diagonals in a Matrix/List of Lists in Python
Matrix Flip Horizontal or Vertical
Why Is This Python Script With Matplotlib So Slow
Subtract a Value from Every Number in a List in Python
How to Count Values Greater Than the Group Mean in Pandas
Pandas Groupby Columns With Nan (Missing) Values
How to Run an .Ipynb Jupyter Notebook from Terminal
Maximum Characters That Can Be Stuffed into Raw_Input() in Python
Turn the Column Headers into the First Row and Row Headers into the First Column in Pandas Dataframe