Get list value by comparing values - python

I have a list like this:
data.append(
{
"type": type,
"description": description,
"amount": 1,
}
)
Every time there is a new object I want to check if there already is an entry in the list with the same description. If there is, I need to add 1 to the amount.
How can I do this the most efficient? Is the only way going through all the entries?

I suggest making data a dict and using the description as a key.
If you are concerned about the efficiency of using the string as a key, read this: efficiency of long (str) keys in python dictionary.
Example:
data = {}
while loop(): # your code here
existing = data.get(description)
if existing is None:
data[description] = {
"type": type,
"description": description,
"amount": 1,
}
else:
existing["amount"] += 1
In either case you should first benchmark the two solutions (the other one being the iterative approach) before reaching any conclusions about efficiency.

Related

Is there an efficient way to write data to a JSON file using a dictionary in Python?

I'm writing a program in Python to use an API that needs to get input from a JSON payload in a really specific way which is shown below. The poid element will contain a different number with each run of the program, the inventories element contains a list of dictionaries that I am trying to send to the API.
[
{
"poid":"22130",
"inventories":
[
{
"item": "SAMPLE-ITEM-1",
"mfgr": "SAMPLE-MANUFACTURER-1",
"quantity": "1",
"condition": "REF"
},
{
"item": "SAMPLE-ITEM-2",
"mfgr": "SAMPLE-MANUFACTURER-2",
"quantity": "3",
"condition": "REF"
}
]
}
]
The data I need to put into the file is stored in a dictionary and a list as shown below. For simplicity of this post, I'm showing what the dictionary and list would look like after another method creates them. I'm not sure if this is the most efficient way of storing this data when I'm having to write it to JSON.
pn_and_mfgr_dict = {'SAMPLE-ITEM-1': 'SAMPLE-MANUFACTURER-1', 'SAMPLE-ITEM-2': 'SAMPLE-MANUFACTURER-2'}
quantities = ["1","3"]
poid = 22130 #this will be different each run
If it makes sense from what I've written above, I need to generate a JSON file that looks like the first codeblock given the information from the second codeblock. The item at index 0 in the quantities list corresponds to the first key/value pair in the dictionary and so on. The "condition" value in the first codeblock will always have "REF" as its value for my use, but I need to also include that in the final payload that gets sent to the API. Since the part number and manufacturer dictionary will be a different length with each run, I also need this method to work regardless of how many values are in the dictionary. This dictionary and the quantities list will always be the same length though. I think the best way I can solve this is making a for loop that iterates through the dictionary and puts respective data where it needs to be, then reading the file when the for loop is done and sending it as the payload but please correct me if there's a better way to do this like storing everything in variables. I also have no experience with JSON so I have attempted to use JSON libraries to accomplish this with no idea what I'm doing wrong. I can edit this with my attempts tonight but I wanted to post this as soon as possible.
Here is one possible solution:
import json
pn_and_mfgr_dict = {
'SAMPLE-ITEM-1': 'SAMPLE-MANUFACTURER-1',
'SAMPLE-ITEM-2': 'SAMPLE-MANUFACTURER-2'
}
quantities = ['1', '3']
poid = 22130
payload = {
'poid': poid,
'inventories': [{
'item': item,
'mfgr': mfgr,
'quantity': quantity,
'condition': 'REF'
} for (item, mfgr), quantity in zip(pn_and_mfgr_dict.items(), quantities)]
}
print(json.dumps(payload, indent=2))
The code above will result in:
{
"poid": 22130,
"inventories": [
{
"item": "SAMPLE-ITEM-1",
"mfgr": "SAMPLE-MANUFACTURER-1",
"quantity": "1",
"condition": "REF"
},
{
"item": "SAMPLE-ITEM-2",
"mfgr": "SAMPLE-MANUFACTURER-2",
"quantity": "3",
"condition": "REF"
}
]
}
Naturally, you can adjust that for multiple poids with something like this:
poids = [22130, 22131, 22132]
for poid in poids:
# implement here the logic to get items and quantities for
# each poid
payload = {
'poid': poid,
'inventories': [{
'item': item,
'mfgr': mfgr,
'quantity': quantity,
'condition': 'REF'
} for (item, mfgr), quantity in zip(pn_and_mfgr_dict.items(), quantities)]
}
print(json.dumps(payload, indent=2))
You will need to change it to have the correspondents items and quantities for each poid, and I leave that as starting point for you to implement.
Your second block is your input, so you could immediately start by write down a function taking those input and returning a JSON string.
import json
from typing import Dict, List
def jsonify_data(pn_and_mfgr_dict: Dict, quantities: List, poid: int):
constructed_data = [] # TODO
return json.dumps(constructed_data)
Then you could start working on using the inputs to construct the output data you desired. And you already know how to do it.
I think the best way I can solve this is making a for loop that iterates through the dictionary and puts respective data where it needs to be
Yes, that's the way to do it.
Here's my version of solution:
import json
from typing import Dict, List
def jsonify_data(pn_and_mfgr_dict: Dict, quantities: List, poid: int):
inventories = [
{
'item': item,
'mfgr': mfgr,
'quantity': quantity,
'condition': 'REF',
} for (item, mfgr), quantity in zip(pn_and_mfgr_dict.items(), quantities)
]
constructed_data = [
{
'poid': f'{poid}',
'inventories': inventories,
}
]
return json.dumps(constructed_data)
import json
data = {'inventories': [{'SAMPLE-ITEM-1': 'SAMPLE-MANUFACTURER-1'}, {'SAMPLE-ITEM-2': 'SAMPLE-MANUFACTURER-2'}]}
quantities = ["1", "3"]
poid = 22130
# Add poid to data
data['poid'] = poid
# Add quantities to data
for item in data['inventories']:
item['quantity'] = quantities.pop(0)
# Serializing json
json_object = json.dumps(data, indent=4)
print(json_object)

How do I change all the keys of a Python dictionary, if the values of said keys are nested dictionaries?

I am working on a headache of a college project in Python, and one of the functions basically has to write a dictionary (which cointains nested dictionaries) into a csv file, and later read from the said file, place it into a new dictionary, and return that new dictionary to the user.
Now, the keys of the said dictionary are of type int, but obvsiouly after being read from the file and written into the new dictionary, they turn into type str.
The unittests we were given keep failing my function because of this, as they expect the same value that was given to us originally, so I have been struggling with modifying this. Below is a (hand-crafted) example of that dictionary that I was practicing on, but still couldn't seem to get the change to take place:
dictionary = {
"0": {
"name": "gary",
"last_name": "john",
"age": 13
},
"1": {
"name": "larry",
"last_name": "boyle",
"age": 10
},
"2": {
"name": "banji",
"last_name": "buas",
"age": 20
}
}
for i in dictionary.items(): #this gives us a tuple
change = list(i) #convert tuple to list
change[0] = int(change[0]) #change each str to int
i = tuple(change) #convert back to tuple
This approach only seems to work within the for-loop, but as soon as the loop ends, and I try printing out the 'new' dict, all I get is the same old one. Can anyone help with this problem?

How to extract the given keys in one dictionary from another into a new dictionary (Python)

I'm trying to practice sets and dictionaries, and one thing I've been finding is myself stuck on this practice problem over and over.
For example if I have a dictionary like
employees =[
{
"name": "Jamie Mitchell",
"job": "Head Chef",
"city": "Toronto",
},
{
"name": "Michell Anderson",
"job": "Line Cook",
"city": "Mississauga",
}
]
How would I extract the second part of the dictionary from the first in order to only have the information on the right be in a new dictionary?
Quick Answer:
employees is a list of dictionaries so you can just directly index the list to get Michell:
newDict = employees[1]
More Detailed Answer:
Firstly, here is how you create a key-value pair in a dictionary:
dct = {}
dct['color'] = 'blue' # dct = {'color':'blue'}
Knowing this, all you would need to copy a dictionary is the keys and values. You can use the .keys(),.values(), and .items() methods of dictionaries to do this.
dct.keys() # returns a list of all the keys -> ['color']
dct.values() # returns a list of all the values -> ['blue']
dct.items() # return a list of all the pairs as tuples -> [('color','blue')]
There are other options to copy as another user has mentioned however I strongly suggest you get used to work with the 3 methods listed above. If you haven't already, make sure you are really comfortable with lists before you jump into dictionaries and combined structures. You already seem to know how to work loops so hopefully this is helpful enough, good luck!
You have them backwards; the outer one [] is a list. The inner ones {} are dictionaries.
You can get the second one with employees[1] (indexing starts from 0) or the last one with employees[-1] (in this case they are the same).
If you need a copy, you can call .copy() on the result:
second_employee = employees[1]
copied_details = second_employee.copy()

Reference all indexes in list and check for existence of value in python

I'm trying to create if block in my python3 script that checks if a value exists within a list I pull from JSON. The JSON data is below:
[
{
"id": 59616405645,
"name": "Foo"
},
{
"id": 990164054345,
"name": "FindMe"
},
{
"id": 2009167874,
"name": "Bar"
}
]
I'm trying to determine whether or not the value of Bar exists within the list. To do so I'm doing the following which directly references the index:
if "FindMe" in m_orgs[1].values():
print("Yo it's here")
else:
print("Yo it's not here.")
But the JSON data I'm pulling will always have different results and we will never know the index numbers, so direct reference will not work. How do I reference all indexes in a list at once?
You can't reference all indexes at once, but you can loop through them, and stop as soon as you find the first existence. Something like:
found = any("findMe" in item.values() for item in m_orgs)
This line will stop the execution when it finds the first True value. So worst case, it will look through every position and not find anything.
You can use any() like this:
if any(d['name'] == 'Foo' for d in json):
do this
You can first translate the original json data to set of data, and then simply check through set operations,
name_set = {org['name'] for org in m_orgs}
print 'FindMe' in name_set

Python - Replace value in JSON file from second file if keys match

I have two JSON files that look like this
{"type": "FeatureCollection", "features": [{ "type": "Feature", "properties": { **"id"**: "Carlow", **"density"**: "0" } , "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -6.58901, 52.906464 ], [ -6.570265, 52.905682 ], [ -6.556207, 52.906464 ],
Second JSON file
{"features": [{"**count**": 2, "name": "**Sligo**"}, {"count": 3"name":"Fermanagh"},{"count": 1, "name": "Laois"},
I am trying to check if "id" in the first file matches with "name" in the second file and if so change the value for "density" to the value for "count" from the second file. I am looking at using recursion from a similar question I found here Replace value in JSON file for key which can be nested by n levels but it only checks if one key matches and changes value. I need two keys to match before changing values. This is the code I have used so far but not sure how to add two keys and two values. I use Counter to count the number of times a string appears and save it to county_names.json, which is my second JSON file. ire_countiesTmp.json is my first file that I am trying to replace the values with from the second file. Im not sure how to do this with Python as only started learning it. Any help would be great, or if you know a better way. Thanks
import json, pprint
from collections import Counter
with open('../county_names.json') as data_file:
county_list = json.load(data_file)
for i in county_list:
c = Counter(i for i in county_list)
for county,count in c.iteritems():
with open('ire_countiesTmp.json') as f:
def fixup(adict, k1, v1, k2, v2):
for key in adict.keys():
if adict[key] == v1:
adict[key] = v
elif type(adict[key]) is dict:
fixup(adict[key], k, v)
#pprint.pprint( data )
fixup(data, 'id', county, 'density', count)
pprint.pprint( data )
Generally speaking, recursion is not a good idea in Python. The compiler/interpreter does not handle it well and it becomes terribly slow, as there is no tail recursion optimisation: Why is recursion in python so slow? .
A possible brute-force-solution that assumes you have converted your JSON-data into a dict could look like this:
def fixup_dict_a_with_b(a, b):
for feature_a in a["features"]:
for feature_b in b["features"]:
if feature_a["properties"]["id"] == feature_b["name"]:
feature_a["properties"]["density"] = feature_b["count"]
break
This can of course be "abstractified" to your liking. ;)
Other, more elegant solutions exist, but this one is straightforward and easy to get when you just started to use Python. (Eventually, you might want to look into pandas, for example.)

Categories