Iterating through and adding multiple Json files to a dictionary - python

So my question is this. I have these JSON files stored in a list called json_list
['9.json',
'8.json',
'7.json',
'6.json',
'5.json',
'4.json',
'3.json',
'2.json',
'10.json',
'1.json',]
Each of these files contains a dictionary with an (ID NUMBER: Rating).
This is my code below. The idea is to store all of the keys and values of these files into a dictionary so it will be easier to search through. I've separated the keys and values so it will be easier to add into the dictionary. The PROBLEM is that this iteration only goes through the file '1.json' and then stops. I'm not sure why its not going through all 10.
for i in range(len(json_list)):
f = open(os.path.join("data", json_list[i]), encoding = 'utf-8')
file = f.read()
f.close()
data = json.loads(file)
keys = data.keys()
values = data.values()

Here:
data = json.loads(file)
keys = data.keys()
values = data.values()
You're resetting the value for keys and values instead of appending to it.
Maybe try appending them, something like (The dictionary keys MUST be unique in each file or else you'll be overwriting data):
data = json.loads(file)
keys += list(data.keys())
values += list(data.values())
Or better yet just append the dictionary (The dictionary keys MUST be unique in each file or else you'll be overwriting data):
all_data = {}
for i in range(len(json_list)):
f = open(os.path.join("data", json_list[i]), encoding = 'utf-8')
file = f.read()
f.close()
data = json.loads(file)
all_data = {**all_data, **data}
Working example:
import json
ds = ['{"1":"a","2":"b","3":"c"}','{"aa":"11","bb":"22","cc":"33", "dd":"44"}','{"foo":"bar","eggs":"spam","xxx":"yyy"}']
all_data = {}
for d in ds:
data = json.loads(d)
all_data = {**all_data, **data}
print (all_data)
Output:
{'1': 'a', '2': 'b', '3': 'c', 'aa': '11', 'bb': '22', 'cc': '33', 'dd': '44', 'foo': 'bar', 'eggs': 'spam', 'xxx': 'yyy'}
If the keys are not unique try appending the dictionaries to a list of dictionaries like this:
import json
ds = ['{"1":"a","2":"b","3":"c"}','{"aa":"11","bb":"22","cc":"33", "dd":"44"}','{"dd":"bar","eggs":"spam","xxx":"yyy"}']
all_dicts= []
for d in ds:
data = json.loads(d)
all_dicts.append(data)
print (all_dicts)
# to access key
print (all_dicts[0]["1"])
Output:
[{'1': 'a', '2': 'b', '3': 'c'}, {'aa': '11', 'bb': '22', 'cc': '33', 'dd': '44'}, {'dd': 'bar', 'eggs': 'spam', 'xxx': 'yyy'}]
a

Related

Appending dictionary to list with different value same key

I have a list of dictionaries, that have same keys and some have different values for those keys. I am trying to append the dictionaries that have different values from the list to keep track of the different values and I would concatenate the values of other keys. For example, I am storing 'a' keys with same values and concatenating the 'b' values that have same 'a':'1'
input list: d = [{'a': '1', 'b': '3'}, {'a': '2', 'b': '4'}, {'a': '1', 'b':'5'}]
output list: p = [{'a':'1', 'b': '35'}, {'a': '2', 'b': '4'}]
So far, I tried the following code, but it doesnt recognize the different values
length = len(p)
j = 0
for i in d:
while j < length:
if p[j]['a'] is not i['a']:
p.append({'a', p[j]['a']})
else:
p[j]['b'] += i['b']
j += 1
j = 0
any tips would be appreciated
Use a dictionary that has the a values as its keys so you don't have to loop through the result list for a matching a.
temp_dict = {}
for item in d:
if item['a'] in temp_dict:
temp_dict[item['a']]['b'] += item['b']
else:
temp_dict[item['a']] = item.copy()
p = list(temp_dict.values())

Sort a python dictionary based on input value?

I have a dictionary with four keys a,b,c,d with values 100,200,300,400
list1 = {'a':'100','b':'200','c':'300','d':'400'}
And a variable inputs.
inputs = 'c'
If inputs is c. The list1 dictionary has to be sorted based on it.
inputs = 'c'
list1 = {'c':'300','a':'100','b':'200','d':'400'}
inputs = 'b'
list1 = {'b':'200','a':'100','c':'300','d':'400'}
In Python3.7+ dict keys are stored in the insertion order
k ='c'
d={k:list1[k]}
for key in list1:
if key!=k:
d[key]=list1[key]
Output
{'c': '300', 'a': '100', 'b': '200', 'd': '400'}
Seems like you just want to rearrange your dict to have the chosen value at the front, then the remaining keys afterwards:
dict1 = {'a':'100','b':'200','c':'300','d':'400'}
key = 'c'
result = {key: dict1[key], **{k: v for k, v in dict1.items() if k != key}}
print(result)
# {'c': '300', 'a': '100', 'b': '200', 'd': '400'}
The ** simply merges the leftover filtered keys with key: dict1[key].
If you just want to change the position to the first one a given value if it exists, it could be done in the following way:
list1 = {'a':'100','b':'200','c':'300','d':'400'}
inputs = 'c'
output = {}
if inputs in list1.keys():
output[inputs] = list1.get(inputs)
for i in list1.keys():
output[i] = list1[i]
Output;
{'c': '300', 'a': '100', 'b': '200', 'd': '400'}
Here's a one-liner:
d = {'a':'100','b':'200','c':'300','d':'400'}
i = input()
d = {i:d[i],**{k:d[k] for k in d if k!=i}}
print(list1)
Input:
c
Output:
{'a': '100', 'b': '200', 'd': '400', 'c': '300'}

How to create a dictionary from a txt file on Python

This is the txt file content I have:
salesUnits:500
priceUnit:11
fixedCosts:2500
variableCostUnit:2
I need to create a dictionary in Python that will read the file and make the keys the salesUnits etc. and the values the numbers. The code I have so far will only print the variable cost per unit:
with open("myInputFile.txt") as f:
content = f.readlines()
myDict = {}
for line in content:
myDict=line.rstrip('\n').split(":")
print(myDict)
How can I fix the code so that all key and value pairs show up? Thank you!
You're overwriting myDict each time you call myDict=line.rstrip('\n').split(":"). The pattern to add to a dictionary is dictionary[key] = value.
myDict = {}
with open("myInputFile.txt") as f:
for line in f:
key_value = line.rstrip('\n').split(":")
if len(key_value) == 2:
myDict[key_value[0]]=key_value[1]
print(myDict)
outputs
{'fixedCosts': '2500', 'priceUnit': '11', 'variableCostUnit': '2', 'salesUnits': '500'}
Using a simple dict comprehension will handle this:
with open('testinput.txt', 'r') as infile:
dict = {
line.strip().split(':')[0]:
int(line.strip().split(':')[1])
if line.strip().split(':')[1].isdigit()
else
line.strip().split(':')[1]
for line in infile.readlines()}
print(dict)
Output:
{'salesUnits': 500, 'priceUnit': 11, 'fixedCosts': 2500, 'variableCostUnit': 2}
If you wish to bring the numbers in as simple strings, just use:
dict = {
line.strip().split(':')[0]:
line.strip().split(':')[1]
for line in infile.readlines()}
Note also that you can add handling for other data types or data formatting using additional variations of:
int(line.strip().split(':')[1])
if line.strip().split(':')[1].isdigit()
else
myDict = {}
with open('dict.txt', 'r') as file:
for line in file:
key, value = line.strip().split(':')
myDict[key] = value
print myDict
Output:
{'fixedCosts': '2500', 'priceUnit': '11', 'variableCostUnit': '2', 'salesUnits': '500'}

Defaultdict appending trick

I have a text file where elements are stored in two column like the following:
a 1,a 3,a 4,b 1,b 2,b 3,b 4,c 1,c 2.... etc
The file contains two columns, one is the key a,b,c etc, and the other is the elements 1,2,3,4 etc.
I stored these items using defaultdict and appended them.
The items in the default dict are:
defaultdict(<type 'list'>, `{'a': ['0', '1', '2', '3', '4'], 'c': ['1', '2'], 'b': ['1', '2', '3', '4']}`)
I used following command:
from collections import defaultdict
positions = defaultdict(list)
with open('test.txt') as f:
for line in f:
sob = line.split()
key=sob[0]
ele=sob[1]
positions[key].append(ele)
print positions
insted of defaultdict you can use OrderedDict
from collections import OrderedDict
positions = OrderedDict()
with open('test.txt') as f:
for line in f:
key, ele = line.strip().split()
positions[key] = positions.get(key, []) + [ele]
print positions

Importing/Exporting a nested dictionary from a CSV file

So I have a CSV file with the data arranged like this:
X,a,1,b,2,c,3
Y,a,1,b,2,c,3,d,4
Z,l,2,m,3
I want to import the CSV to create a nested dictionary so that looks like this.
data = {'X' : {'a' : 1, 'b' : 2, 'c' : 3},
'y' : {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4},
'Z' : {'l' : 2, 'm' :3}}
After updating the dictionary in the program I wrote (I got that part figured out), I want to be able to export the dictionary onto the same CSV file, overwriting/updating it. However I want it to be in the same format as the previous CSV file so that I can import it again.
I have been playing around with the import and have this so far
import csv
data = {}
with open('userdata.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
data[row[0]] = {row[i] for i in range(1, len(row))}
But this doesn't work as things are not arranged correctly. Some numbers are subkeys to other numbers, letters are out of place, etc. I haven't even gotten to the export part yet. Any ideas?
Since you're not interested in preserving order, something relatively simple should work:
import csv
# import
data = {}
with open('userdata.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
a = iter(row[1:])
data[row[0]] = dict(zip(a, a))
# export
with open('userdata_exported.csv', 'w') as f:
writer = csv.writer(f)
for key, values in data.items():
row = [key] + [value for item in values.items() for value in item]
writer.writerow(row)
The latter could be done a little more efficiently by making only a single call to thecsv.writer's writerows()method and passing it a generator expression.
# export2
with open('userdata_exported.csv', 'w') as f:
writer = csv.writer(f)
rows = ([key] + [value for item in values.items() for value in item]
for key, values in data.items())
writer.writerows(rows)
You can use the grouper recipe from itertools:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)
This will group your data into the a1/b2/c3 pairs you want. So you can do data[row[0]] = {k: v for k, v in grouper(row[1:], 2)} in your loop.
from collections import defaultdict
data_lines = """X,a,1,b,2,c,3
Y,a,1,b,2,c,3,d,4
Z,l,2,m,3""".splitlines()
data = defaultdict(dict)
for line in data_lines:
# you should probably add guards against invalid data, empty lines etc.
main_key, sep, tail = line.partition(',')
items = [item.strip() for item in tail.split(',')]
items = zip(items[::2], map(int, items[1::2])
# data[main_key] = {key : value for key, value in items}
data[main_key] = dict(items)
print dict(data)
# {'Y': {'a': '1', 'c': '3', 'b': '2', 'd': '4'},
# 'X': {'a': '1', 'c': '3', 'b': '2'},
# 'Z': {'m': '3', 'l': '2'}
# }
I'm lazy, so I might do something like this:
import csv
data = {}
with open('userdata.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
data[row[0]] = dict(zip(row[1::2], map(int,row[2::2])))
which works because row[1::2] gives every other element starting at 1, and row[2::2 every other element starting at 2. zip makes a tuple pair of those elements, and then we pass that to dict. This gives
{'Y': {'a': 1, 'c': 3, 'b': 2, 'd': 4},
'X': {'a': 1, 'c': 3, 'b': 2},
'Z': {'m': 3, 'l': 2}}
(Note that I changed your open to use 'rb', which is right for Python 2: if you're using 3, you want 'r', newline='' instead.)

Categories