Splitting dictionary items into smaller dictionaries based on condition
One way would just be to keep track of how many times you've seen a given parent. The first time you see parent 'a', you add that partial/parent pair to the first group; the second, to the second group, etc.
For example:
def split_into_groups(transactions):
counts = {}
out_groups = {}
for partial, parent in transactions:
counts[parent] = target = counts.get(parent, 0) + 1
out_groups.setdefault(target, {})[partial] = parent
return out_groups
gives me
In [9]: split_into_groups(zip(partials, parents))
Out[9]:
{1: {1: 'a', 2: 'b', 3: 'c', 4: 'd', 7: 'f'},
2: {5: 'a', 6: 'd', 8: 'c'},
3: {9: 'c', 10: 'a'}}
This uses counts.get
to get a default value of 0 if the count isn't present yet, and out_groups.setdefault
to make a default empty dictionary and put it into out_groups if we haven't seen that target count yet.
If you had to handle the case of duplicate partials, you could replace the setdefault line with
out_groups.setdefault(target, []).append((partial, parent))
which would turn the group members into lists of tuples instead of dictionaries:
{1: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (7, 'f')],
2: [(5, 'a'), (6, 'd'), (8, 'c')],
3: [(9, 'c'), (10, 'a')]}
Python Split Dictionary into Smaller Dictionaries by Threshold Value
First of all, what you are describing here is very close to (or is ?) the Multiple knapsack problem. There are a numerous way to solve this problem, depending on what conditions you impose on the results.
I recommended you read this page and the resources associated with it to better frame your desired output. For example, can we omit items ? What if we cannot satisfy your constraint on the results (within [195,205]) with the current list of items ?
Using pure python, a naive approach to reduce code amount using a greedy approach could be (given that your dictionary is sorted in descending order):
# Initialize a list of dictionaries to fill
dicts = [{},{},{}]
# Define a counter
i = 0
# Define your maximum value
max_value = 205
for k,v in dict_sports.items():
for i in range(len(dicts)):
if sum(dicts[i].values()) + v < max_value:
dicts[i].update({k:v})
break
i+=1
for d in dicts:
print("---- {} ----".format(sum(d.values())))
print(d)
Giving
---- 203 ----
{'Skateboarding': 163, 'Baseball': 30, 'Skiing': 10}
---- 199 ----
{'Bowling': 134, 'Wrestling': 57, 'Boxing': 8}
---- 198 ----
{'Rugby': 83, 'Badminton': 24, 'Volleyball': 22, 'Basketball': 18, 'Football': 16, 'Weightlifting': 15, 'Golf': 14, 'Cricket': 6}
Note that this solution may skip items if the sum condition is not met for all dictionary.
How to split a python dictionary into multiple dictionaries based on values
Here is a general approach using a nested collections.defaultdict
:
def categorize_dicts(dictionary):
dfd = defaultdict(defaultdict)
for k, v in d.items():
for i,j in zip(v, v[1:]):
dfd[j-i].setdefault(k,[]).extend((i, j))
return dfd
Demo:
In [28]: d = {'A': [0, 2, 5],
...: 'B': [1],
...: 'C': [3, 6, 9],
...: 'D': [4, 7, 10],
...: 'E': [8, 11, 13],
...: 'F': [12, 15, 17],
...: 'T': [19]}
...:
In [29]: categorize_dicts(d)
Out[29]:
defaultdict(collections.defaultdict,
{2: defaultdict(None, {'A': [0, 2], 'E': [11, 13], 'F': [15, 17]}),
3: defaultdict(None,
{'A': [2, 5],
'C': [3, 6, 6, 9],
'D': [4, 7, 7, 10],
'E': [8, 11],
'F': [12, 15]})})
Dynamically split a dictionary into multiple dictionaries in python3.6 depending on input provided
This code handles any keys starting with letters and ending in a number, which can contain any number of digits. If a key is found that doesn't end in a number it prints an error message, a proper program should do better error handling.
It saves each resulting dictionary into a dictionary sub_dicts
, so it doesn't need to sort the input data.
import re
# Make a regex that finds the number
pat = re.compile(r'\d+')
my_dict = {
'name1': 'abc', 'job1': 'xyz', 'pos1': 'tak', 'phone1': 12345,
'name2': 'pqr', 'job2': 'ftr', 'pos2': 'lkj', 'phone2': 27654,
'name3': 'swq', 'job3': 'nme', 'pos3': 'mnb', 'phone3': 98421,
'bad': 'bad_data',
}
# Separate the data based on the trailing number of each key.
sub_dicts = {}
for k, v in my_dict.items():
m = pat.search(k)
if m:
num = m.group()
sub_dicts.setdefault(num, {})[k] = v
else:
print('Invalid key:', k, v)
for k in sub_dicts.keys():
print(sub_dicts[k])
output
Invalid key: bad bad_data
{'name1': 'abc', 'job1': 'xyz', 'pos1': 'tak', 'phone1': 12345}
{'name2': 'pqr', 'job2': 'ftr', 'pos2': 'lkj', 'phone2': 27654}
{'name3': 'swq', 'job3': 'nme', 'pos3': 'mnb', 'phone3': 98421}
(Python) Split dictionary in two based on a property
One line solution (with lower_excluded_users
which I couldn't resist making)
included, excluded = dict(), dict()
# ssly, you don't have to do this everytime
lower_excluded_users = [x.lower() for x in EXCLUDED_USERS]
# and now the one-line answer using if-else-for construct with
# v substituted by D[k]. And instead of using `for k, v in dicn.items()`
# I have used [... for aKey in dicn.keys()]
[ excluded.update({aKey: users[aKey]}) \
if any(x in users[aKey]["name"].lower() for x in lower_excluded_users) \
else \
included.update({aKey: users[aKey]}) \
for aKey in users.keys()
]
Or one without beautification:
[excluded.update({aKey: users[aKey]}) if any(x in users[aKey]["name"].lower() for x in lower_excluded_users) else included.update({aKey: users[aKey]}) for aKey in users.keys()]
Split dictionary based on a value
Just do something like
key = 378.2
dd = {517.1: 'h', 182.8:'o', 306.5:'l', 378.2:'a'}
d1 = {k:dd[k] for k in dd if k < key}
d2 = {k:dd[k] for k in dd if k > key}
How to split dictionary according to key and value into multiple dictionaries using indexes?
You can put your for
loop in dictionary comprehension:
selected_stalls = []
Day_of_week = 'Mon'
time_of_meal = 'None'
raw_list_stallinfo = {'MiniWok_Stall_Menu1': 'Monday_Tuesday@Wednesday', 'Item1: Seafood HorFun@MiniWok_Stall_Menu1': '$4.50', 'Item2: Fish HorFun@MiniWok_Stall_Menu1': '$3.50', 'Item3: Chicken Horfun@MiniWok_Stall_Menu1': '$3.50', 'remark:@MiniWok_Stall_Menu1': 'None', 'MiniWok_Stall_Menu2': 'Thursday_Friday@Sunday', 'Item1: Seafood Fried Rice@MiniWok_Stall_Menu2': '$4.50', 'Item2: Salted Fish Fried Rice@MiniWok_Stall_Menu2': '$3.50', 'Item3: Chicken Fried Rice@menu2': '$3.50', 'remark:@MiniWok_Stall_Menu2': 'None', 'MiniWok_Stall_Menu3': 'Monday_Tuesday_Wednesday_Thursday_Friday@Sunday', 'Item1: Chicken Porridge@MiniWok_Stall_Menu3': '$3.00', 'Item2: Century-egg porridge@MiniWok_Stall_Menu3': '$4.00', 'remark:@MiniWok_Stall_Menu3': 'Breakfast Only'}
raw_list = {raw_list_idx: raw_list_key for raw_list_idx, raw_list_key in enumerate(raw_list_stallinfo.keys()) if Day_of_week in raw_list_stallinfo[raw_list_key]}
selected_stalls.append(raw_list)
print(selected_stalls)
This will give the output:
[{0: 'MiniWok_Stall_Menu1', 10: 'MiniWok_Stall_Menu3'}]
To find the time_of_meal
location:
location = {i: k for i, k in enumerate(raw_list_stallinfo.values()) if k == time_of_meal}
print(location)
Which gives the locations as:
{4: 'None', 9: 'None'}
Then to find the remark
without hard-coding you can marry it up with the location above:
remark_location = {i: k for i, k in raw_list_stallinfo.items() if k == time_of_meal}
print(remark_location)
Which returns the full Key and Value:
{'remark:@MiniWok_Stall_Menu1': 'None', 'remark:@MiniWok_Stall_Menu2': 'None'}
Related Topics
How to Update Sqlalchemy Orm Object by a Python Dict
Json.Loads() Decodes Only With Raw String Literal
Python: Pickle.Load() Raising Eoferror
How to Change a Two Dimensional Array to One Dimensional
Anaconda Installed But Cannot Launch Navigator
How to Tell Python to Convert Integers into Words
How to Maximize a Plt.Show() Window Using Python
How to Count Values Greater Than the Group Mean in Pandas
How to Merge Json Objects Containing Arrays Using Python
Why Is This Going Out of Range
Python Executable Not Finding Libpython Shared Library
How to Block Comment Code in the Ipython Notebook
Python Anaconda - How to Safely Uninstall
Google Chrome Closes Immediately After Being Launched With Selenium
How to Remove Unused Packages from Virtualenv
How to Write 2 Lists of Items in 2 Columns Instead of 2 Arrays