How to get all full paths to all child elements - python-3.x

Given a tree based of list of lists:
tree = [
"A",
[
"B1",
[
"C"
]
],
[
"B2",
[
"C",
[
"D1",
[
"E1"
],
[
"E2"
]
],
[
"D2"
]
]
]
]
I want to get the full path to all child elements as concatenated string in a list.
result = [
'A>B1>C',
'A>B2>C>D1>E1',
'A>B2>C>D1>E2',
'A>B2>C>D2'
]
The delimiter > is changeable.
I tried different things with recursion and yield. But my head is burning.

Try this it works.
def leave_paths(current):
if len(current) == 1:
return [current]
# Take all branches, get the paths for the branch, and prepend
return [[current[0]] + path for branch in current[1:] for path in leave_paths(branch)]
output = ['>'.join(sub_list) for sub_list in leave_paths(s)]
print(output)
Output
['A>B1>C', 'A>B2>C>D1>E1', 'A>B2>C>D1>E2', 'A>B2>C>D2']

Smth like this
def findLeaves(tree):
name=tree[0]
If len(tree)==1:
return [name]
else:
return [name+"->"+path for branch in tree[1:] for path in findLeaves(branch)]

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()

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

List comprehension to dynamically populate attribute of object

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())

Text.Hamlet.Runtime - nesting HamletData?

I am rendering Hamlet templates using the Runtime module. The following works as promised with the example data:
let hamletDataMap = Map.fromList
[ ("name", "Michael")
, ("hungry", toHamletData True) -- always True
, ("foods", toHamletData
[ "Apples"
, "Bananas"
, "Carrots"
])
]
But I can't see any way for me to render nested data. For instance if I have a list of metadata of various fruits, I would like to do something like:
let hamletDataMap = Map.fromList
[ ("name", "Michael")
, ("hungry", toHamletData True) -- always True
, ("fruits", toHamletData
[ [ ("name", "apple")
, ("taste", "sour")
]
, [ ("name", "..")
, ("taste", "...")
]
])
]
In the Text.Hamlet.RT there is the HDList [HamletMap] which looks kindof strange but still promising. I can creates instances of HDList but it gives me type mismatch HamletData with actual type RT.HamletData url0.
I'm thankful for any ideas or suggestions.

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