List comprehension to dynamically populate attribute of object - python-3.x

What’s the correct way to dynamically populate the list given to the attribute Value? At the moment its its fixed to 3 (0-2), but would be more useful if it was based on INSTANCE_PARAMS[i]["instances"].
I was thinking along the lines of list comprehension but unsure how to write it into the code.
for i in INSTANCE_PARAMS:
output = template.add_output([
Output(
str(INSTANCE_PARAMS[i]["name"]).capitalize() + "Ips",
Description="IPs for " + str(INSTANCE_PARAMS[i]["name"]),
Value=Join(",", [
GetAtt(ec2.Instance(INSTANCE_PARAMS[i]["name"] + "0"), "PrivateIp"),
GetAtt(ec2.Instance(INSTANCE_PARAMS[i]["name"] + "1"), "PrivateIp"),
GetAtt(ec2.Instance(INSTANCE_PARAMS[i]["name"] + "2"), "PrivateIp"),
],
),
)
],
)
INSTANCE_PARAMS = {
"masters": {
"name": "master",
"instances": 3,
"image_id": "ami-xxxxxxxxxx",
"instance_type": "t1.micro",
"security_group_id": [
"MasterSG",
"ClusterSG"
],
},
}

Achieved it with the following:
template = Template()
for i in INSTANCE_PARAMS:
# declared a new list
tag_value = []
# got the counter
for r in range(INSTANCE_PARAMS[i]["instances"]):
# added each one to the new list
tag_value.append(GetAtt(ec2.Instance(INSTANCE_PARAMS[i]["name"] + str(r)), "PrivateIP"))
output = template.add_output([
Output(
str(INSTANCE_PARAMS[i]["name"]).capitalize() + "Ips",
Description="IPs for " + str(INSTANCE_PARAMS[i]["name"]),
# passed in the list
Value=Join(",", tag_value,
),
)
],
)
print(template.to_yaml())

Related

Replace value of a specific key in json file for multiple files

I am preparing a test data for the feature testing .
I have 1000 json file with same below structure in local folder .
I need to replace two key from all the places and create 1000 different json .
Key that needs to be replaced is
"f_ID": "80510926" and "f_Ctb": "10333"
"f_ID": "80510926" appears in all the array but "f_Ctb": "10333" appear only once .
The replaced value can be running number 1 to 100 in all files .
Can some one suggest how we can do this python to create 1000 files
{
"t_A": [
{
"f_ID": "80510926",
"f_Ctb": "10333",
"f_isPasswordProtected": "False"
}
],
"t_B": [
{
"f_ID": "80510926",
"f_B_Company_ID": "10333",
"f_B_ID": "1",
"f_ArriveDate": "20151001 151535.775"
},
{
"f_ID": "80510926",
"f_B_Company_ID": "10333",
"f_B_ID": "1700",
"f_ArriveDate": "20151001 151535.775"
}
],
"t_C": [
{
"f_ID": "80510926",
"f_Set_Code": "TRBC ",
"f_Industry_Code": "10 ",
"f_InsertDate": "20151001 151535.775"
},
],
"t_D": [
{
"f_ID": "80510926",
"f_Headline": "Global Reinsurance: Questions and themes into Monte Carlo",
"f_Synopsis": ""
}
]
}
here is the solution run in the folder where you have 1000 json files.
It will read all the json files and replace the f_ID and f_Ctb with the count and write the file with same file name in output folder.
import os
import json
all_files = os.listdir()
json_files = {f: f for f in all_files if f.endswith(".json")}
json_files_keys = list(json_files.keys())
json_files_keys.sort()
OUTPUT_FOLDER = "output"
if not os.path.exists(OUTPUT_FOLDER):
os.mkdir(OUTPUT_FOLDER)
for file_name in json_files_keys:
f_read = open(file_name, "r").read()
data = json.loads(f_read)
output_data = {}
count = 1
for key, val_list in data.items():
for nest_dict in val_list:
if "f_ID" in nest_dict:
nest_dict["f_ID"] = count
if "f_Ctb" in nest_dict:
nest_dict["f_Ctb"] = count
if key in output_data:
output_data[key].append(nest_dict)
else:
output_data[key] = [nest_dict]
else:
output_data[key] = val_list
count += 1
output_file = open(f"{OUTPUT_FOLDER}/{file_name}", "w")
output_file.write(json.dumps(output_data))
output_file.close()

Find values from the Nested Dict

Something I'm doing incorrect, but I got data with list of nested dict, I need to pull the value and store in the output dict.
Data:
[{
"encoding":"json",
"result": {
"aclList":[
{
"chipName":"",
"countersEnabled":true,
"countersIncomplete":false,
"dynamic":false,
"name":"FW-RULE-IN",
"readonly":false,
"sequence":[
{
"convertSymbols":true,
"sequenceNumber":1,
"text":"TEST: RULE 1"
},
{
"convertSymbols":true,
"sequenceNumber":2,
"text":"TEST: RULE 2"
},
{
"convertSymbols":true,
"sequenceNumber":3,
"text":"TEST: RULE 3"
},]}]}}]
Like to put sequenceNumber, text values in to output result in Dict.
here is the code I got, but not working, how to fix it?
def parse_data(data):
rules = {}
acllist = []
for k, v in data[0].items():
for h, j in k['result'].items():
for i in h['aclList'][0]:
for l in i[0]['sequence']:
rules['NUM'] = int(j['sequenceNumber'])
rules['TEXT_RULES'] = j['text']
acllist.append(rules.copy())
print (j['sequenceNumber'], j['text'])
return acllist
I'm assuming there can be multiple elements to these lists. If there aren't you could simplify to.
for dct in data[0]['result']['aclList'][0]['sequence']:
rules['NUM'] = int(dct['sequenceNumber'])
rules['TEXT_RULES'] = dct['text']
acllist.append(rules.copy())
print (inner['sequenceNumber'], dct['text'])
However if you want to iterate through every list and gather the elements for each version, it would look more like this:
def parse_data(data):
acllist = []
# for each dict in the initial list
for dct in data:
# for each list in the ['aclList'] key of the ['result'] key
for lst in dct['result']['aclList']:
# for each inner dict in the ['sequence'] key
for inner in lst['sequence']:
rules = {}
rules['NUM'] = int(inner['sequenceNumber'])
rules['TEXT_RULES'] = inner['text']
acllist.append(rules.copy())
print (inner['sequenceNumber'], inner['text'])
return acllist
data =[{
"encoding":"json",
"result": {
"aclList":[
{
"chipName":"",
"countersEnabled":True,
"countersIncomplete":False,
"dynamic":False,
"name":"FW-RULE-IN",
"readonly":False,
"sequence":[
{
"convertSymbols":True,
"sequenceNumber":1,
"text":"TEST: RULE 1"
},
{
"convertSymbols":True,
"sequenceNumber":2,
"text":"TEST: RULE 2"
},
{
"convertSymbols":True,
"sequenceNumber":3,
"text":"TEST: RULE 3"
},]}]}}]
print(parse_data(data))
Where you went wrong is that you are iterating through the key/values of you dicts.
for k, v in data[0].items():
k here would contain "encoding" and "result".
And then you are trying to iterate through those keys.
for h, j in k['result'].items():
But what you are essentially doing here is saying:
k = "result"
for h, j in k['result'].items():
Or:
for h, j in "result"['result'].items():
You can see why this would throw an error.

How to append multiple JSON object in a custom list using python?

I have two dictionary (business and business 1). I convert this dictionary into JSON file as (a and b). Then i append this two JSON object in a custom list called "all".
Here, list creation is static, i have to make it dynamic because the number of dictionary could be random. But output should be in same structure.
Here is my code section
Python Code
import something as b
business = {
"id": "04",
"target": b.YesterdayTarget,
'Sales': b.YSales,
'Achievements': b.Achievement
}
business1 = {
"id": "05",
"target": b.YesterdayTarget,
'Sales': b.YSales,
'Achievements': b.Achievement
}
# Convert Dictionary to json data
a= str(json.dumps(business, indent=5))
b= str(json.dumps(business1, indent=5))
all = '[' + a + ',\n' + b + ']'
print(all)
Output Sample
[{
"id": "04",
"target": 55500000,
"Sales": 23366927,
"Achievements": 42.1
},
{
"id": "05",
"target": 55500000,
"Sales": 23366927,
"Achievements": 42.1
}]
Thanks for your suggestions and efforts.
Try this one.
import ast, re
lines = open(path_to_your_file).read().splitlines()
result = [ast.literal_eval(re.search('({.+})', line).group(0)) for line in lines]
print(len(result))
print(result)

Accessing Elements in a nested list in python

I am a newbie in python and I have data in a nested list in this format. I want to do something if the value of age in the dictionaries are equal.
[
[
{
"name":"AAAAA",
"age":"12",
"class":"box"
}
],
[
{
"name":"DDDD",
"age":"10",
"class":"space"
}
],
[
{"name":"BBBB"},
{"age":"16"},
{"class":"cage"}
],
[
{
"name":"EEEE",
"age":"20",
"class":"sage"
}
],
]
The main idea is to store all the ages in a list, get list of duplicate ages and access the dictionary using that list
age_list = []
for l in dict_list:
temp_dict = l[0]
age_list.append(temp_dict["age"])
# get set of duplicates in age list
dup_ages = set([x for x in l if l.count(x) > 1])
for index, age in enumerate(age_list):
for dup_age in dup_ages: # do something for a given duplicate age
if dup_age == age:
dict_list[index] # do something in the dict

Changing the values of a map nested in another map

Using HQL queries I've been able to generate the following map, where the keys represent the month number constant defined in java.util.Calendar, and every value is a map:
[
0:[ client_a:[order1, order2, order3]],
1:[ client_b:[order4], client_c:[order5, order6], client_d:[order7]],
2:[ client_e:[order8, order9], client_f:[order10]]
]
order1, order2, ... are instances of a domain class called Order:
class Order {
String description
Date d
int quantity
}
Now I've got that structure containing orders that belong to some specific year, but I don't really care about the Order object itself. I just want the sum of the quantities of all the orders of each month. So the structure should look something like this:
[
0:[ client_a:[321]],
1:[ client_b:[9808], client_c:[516], client_d:[20]],
2:[ client_e:[22], client_f:[10065]]
]
I don't mind if the values are lists of one element or not lists at all. If this is possible, it would be fine anyway:
[
0:[ client_a:321 ],
1:[ client_b:9808, client_c:516, client_d:20 ],
2:[ client_e:22, client_f:10065 ]
]
I know I have to apply something like .sum{it.quantity} to every list of orders to get the result I want, but I don't know how to iterate over them as they are nested within another map.
Thank you.
Here You go:
class Order {
String description
Date d
int quantity
}
def orders = [
0:[ client_a:[new Order(quantity:1), new Order(quantity:2), new Order(quantity:3)]],
1:[ client_b:[new Order(quantity:4)], client_c:[new Order(quantity:5), new Order(quantity:6)], client_d:[new Order(quantity:7)]],
2:[ client_e:[new Order(quantity:8), new Order(quantity:9)], client_f:[new Order(quantity:10)]]
]
def count = orders.collectEntries { k, v ->
def nv = v.collectEntries { nk, nv ->
[(nk): nv*.quantity.sum()]
}
[(k):(nv)]
}
assert count == [0:[client_a:6], 1:[client_b:4, client_c:11, client_d:7],2:[client_e:17, client_f:10]]
def map = [
0:[ client_a:[[q: 23], [q: 28], [q: 27]]],
1:[ client_b:[[q: 50]], client_c:[[q: 100], [q: 58]], client_d:[[q: 90]]],
2:[ client_e:[[q: 48], [q: 60]], client_f:[[q: 72]]]
]
map.collectEntries { k, v ->
[ k, v.collectEntries { key, val ->
[ key, val*.q.sum() ]
} ]
}
you can also use val.sum { it.q } instead of val*.q.sum()

Resources