How to find List of subMap with nested subMap - groovy

I have a List of Map with nested Map as well as below :-
def list = [
[
"description": "The issue is open and ready for the assignee to start work on it.",
"id": "1",
"name": "Open",
"statusCategory": [
"colorName": "blue-gray",
"id": 2,
"key": "new",
"name": "To Do",
]
],
[
"description": "This issue is being actively worked on at the moment by the assignee.",
"id": "3",
"name": "In Progress",
"statusCategory": [
"colorName": "yellow",
"id": 4,
"key": "indeterminate",
"name": "In Progress",
]
]
]
I have a task to get List of subMap with nested subMap. I'm doing some thing like as below :-
def getSubMap = { lst ->
lst.findResults { it.subMap(["id", "name", "statusCategory"])}
}
println getSubMap(list)
But its give me output as below :-
[
[
"id":1,
"name":"Open",
"statusCategory":[
"colorName":"blue-gray",
"id":2,
"key":"new",
"name":"To Do"
]
],
[
"id":"3",
"name":"In Progress",
"statusCategory":[
"colorName":"yellow",
"id":"4",
"key":"indeterminate",
"name":"In Progress"
]
]
]
As you can see I'm unable to get subMap of statusCategory key Map. Actually I want to get further subMap for nested Maps something like as below :-
[
[
"id":1,
"name":"Open",
"statusCategory":[
"id":"2",
"name":"To Do"
]
],
[
"id":"3",
"name":"In Progress",
"statusCategory":[
"id":"4",
"name":"In Progress"
]
]
]
To achieve this I'm trying as below :-
def getSubMap = { lst ->
lst.findResults { it.subMap(["id", "name", "statusCategory":["id","name"]])}
}
def modifiedList = getSubMap(list)
But it throws me Excpetion. And If I'm doing as below :-
def getSubMap = { lst ->
lst.findResults { it.subMap(["id", "name", "statusCategory"]).statusCategory.subMap(["id","name"])}
}
println getSubMap(list)
It gives only nested subMap as :-
[["id":"2", "name":"To Do"], ["id":"4", "name":"In Progress"]]
could anyone suggest me how to recurselvely find List of subMap with nested subMap if exist?

If your Map nesting is arbitrary, then you might want to consider something like this:
def nestedSubMap
nestedSubMap = { Map map, List keys ->
map.subMap(keys) + map.findAll { k, v -> v instanceof Map }.collectEntries { k, v -> [(k):nestedSubMap(v, keys)] }
}
Given your input and this closure, the following script:
def result = list.collect { nestedSubMap(it, ["id", "name"]) }
println '['
result.each { print it; println ',' }
println ']'
Produces this output:
[
[id:1, name:Open, statusCategory:[id:2, name:To Do]],
[id:3, name:In Progress, statusCategory:[id:4, name:In Progress]],
]

Given the original list, consider this:
def resultList = list.collect {
def fields = ["id", "name"]
def m = it.subMap(fields)
m["statusCategory"] = it["statusCategory"].subMap(fields)
return m
}
which supports these assertions:
assert 1 == resultList[0]["id"] as int
assert "Open" == resultList[0]["name"]
assert 2 == resultList[0]["statusCategory"]["id"] as int
assert "To Do" == resultList[0]["statusCategory"]["name"]
assert 3 == resultList[1]["id"] as int
assert "In Progress" == resultList[1]["name"]
assert 4 == resultList[1]["statusCategory"]["id"] as int
assert "In Progress" == resultList[1]["statusCategory"]["name"]

Related

Arango DB Filter query for print array of value

Given the following document structure:
{
"name": [
{
"use": "official",
"family": "Chalmers",
"given": [
"Peter",
"James"
]
},
{
"use": "usual",
"given": [
"Jim"
]
},
{
"use": "maiden",
"family": "Windsor",
"given": [
"Peter",
"James"
]
}
]
}
Query:
FOR client IN Patient FILTER client.name[*].use=='official' RETURN client.name[*].given
I have telecom and name array.
I want to query to compare if name[*].use=='official' then print corresponding give array.
Expected result:
"given": [
"Peter",
"James"
]
client.name[*].use is an array, so you need to use an array operator. It can be either of the following:
'string' in doc.attribute
doc.attribute ANY == 'string'
doc.attribute ANY IN ['string']
To return just the given names from the 'official' array, you can use a subquery:
RETURN { given:
FIRST(FOR name IN client.name FILTER name.use == 'official' LIMIT 1 RETURN name.given)
}
Alternatively, you can use an inline expression:
FOR client IN Patient
FILTER 'official' IN client.name[*].use
RETURN { given:
FIRST(client.name[* FILTER CURRENT.use == 'official' LIMIT 1 RETURN CURRENT.given])
}
Result:
[
{
"given": [
"Peter",
"James"
]
}
]
In your original post, the example document and query didn't match, but assuming the following structure:
{
"telecom": [
{
"use": "official",
"value": "+1 (03) 5555 6473 82"
},
{
"use": "mobile",
"value": "+1 (252) 5555 910 920 3"
}
],
"name": [
{
"use": "official",
"family": "Chalmers",
"given": [
"Peter",
"James"
]
},
{
"use": "usual",
"given": [
"Jim"
]
},
{
"use": "maiden",
"family": "Windsor",
"given": [
"Peter",
"James"
]
}
]
}
… here is a possible query:
FOR client IN Patient
FILTER LENGTH(client.telecom[* FILTER
CONTAINS(CURRENT.value, "(03) 5555 6473") AND
CURRENT.use == 'official']
)
RETURN {
given: client.name[* FILTER CURRENT.use == 'official' RETURN CURRENT.given]
}
Note that client.telecom[*].value LIKE "..." causes the array of phone numbers to be cast to a string "[\"+1 (03) 5555 6473 82\",\"+1 (252) 5555 910 920 3\"]" against which the LIKE operation is run - this kind of works, but it's not ideal.
CONTAINS() is also faster than LIKE with % wildcards on both sides.
It would be possible that there are multiple 'official' elements, which might require an extra level of array nesting. Above query produces:
[
{
"given": [
[
"Peter",
"James"
]
]
}
]
If you know that there is only one element or restrict it to one element explicitly then you can get rid of one of the wrapping square brackets with FIRST() or FLATTEN().

Python how to check the dictonary have value in list and change to string type?

I have below dictionary in which value for some of keys are appeared as list.
i need to find those values which are list type and need to convert to string
details=
{
"dsply_nm": [
"1981 test test"
],
"eff_dt": [
"2021-04-21T00:01:00-04:00"
],
"exp_dt": [
"2022-04-21T00:01:00-04:00"
],
"pwr": [
"14"
],
"is_excl": [
"true"
],
"is_incl": [
"false"
],
"len": [
"14"
],
"max_spd": [
"14"
],
"id": "58",
"type_nm": "single",
"updt_dttm": "2021-04-21T13:40:11.148-04:00",
"nbr": "3",
"typ": "premium",
"nm": "test"
}
below code not seems to be working and its not returning as string
test={}
for k,v in details.items():
if isinstance(v, list):
test[k]="".join(str(v))
test[k]=v
print(test)
expected should be as below
{'dsply_nm':'1981 test test',
"eff_dt": "2021-04-21T00:01:00-04:00",
"exp_dt":"2022-04-21T00:01:00-04:00",
"pwr":"14",
"is_excl":"true",
"is_incl": "false",
"len":"14",
"max_spd":"14",
"id":"58",
"updt_dttm":"2021-04-21T13:40:11.148-04:00",
"nbr":"3",
"typ": "premium",
"nm":"test"
}
anybody can help on this?
Your code is almost correct - you forgot else clause and should not use str(v) before join.
This code works fine:
test={}
for k,v in details.items():
if isinstance(v, list):
test[k]="".join(v)
else:
test[k]=v
print(test)

Iterate over N nested list and dictionaries

I have the following structure of JSON/Dict.
[
{
"childrens": [
{
"childrens": [
{
"name": "somenam1"
}
],
"name": "B999"
}
],
"name": "11111"
},
{
"childrens": [
{
"childrens": [
{
"name": "somename2"
},
{
"name": "somename3"
}
],
"name": "B5555"
},
{
"childrens": [
{
"name": "somename4"
}
],
"name": "B2222"
}
],
"name": "2222"
}
]
I want to iterate over all dictionaries and list inside root list and create single string for each dictionary inside root list.
Output will look like this (two lines):
1111|B999|somename1
2222|B5555|somename2|somename3|B2222|somename4
Also this is just an example i can have N nested childrens.
Looks like a good candidate for recursion:
def flatten(child):
if not child:
return child
return [child['name']] + [name for c in child.get('childrens', []) for name in flatten(c)]
In []:
for child in data:
print('|'.join(flatten(child)))
Out[]:
11111|B999|somenam1
2222|B5555|somename2|somename3|B2222|somename4
Sure you can just pass add a level arg and return that:
def flatten(child, level=0):
if not child:
return child
return [level] + [l for c in child.get('childrens', []) for l in flatten(c, level+1)]
In []:
for child in data:
print('|'.join(str(level) for level in flatten(child)))
Out[]:
0|1|2
0|1|2|2|1|2
Here's a solution by recursion
data_json = '[{"childrens":[{"childrens":[{"name":"somenam1"}],"name":"B999"}],"name":"11111"},{"childrens":[{"childrens":[{"name":"somename2"},{"name":"somename3"}],"name":"B5555"},{"childrens":[{"name":"somename4"}],"name":"B2222"}],"name":"2222"}]'
data = json.loads(data_json)
def get_names(data_dict):
if ("childrens" in data_dict):
ret_dict = "|".join(map(get_names, data_dict["childrens"]))
return data_dict["name"] + "|" + ret_dict
else:
return data_dict["name"]
def get_all_name(data):
for i in data:
print(get_names(i))
get_all_name(data)

How to find object in python list by attribute

If I have a list created like this:
list = [
{
"id": 1,
"name": "something 1"
},
{
"id": 2,
"name": "something 2"
}
]
and I want to grab information from one of the list items, using the id from the url like this:
#route.app('item/<int:id>')
def item(id):
name = ???
return render_template('index.html', name=name)
how would I get the name of the object in the list with the specific id from the url?
A simple for loop will do your work:
#route.app('item/<int:id>')
def item(id):
some_list = [
{
"id": 1,
"name": "something 1"
},
{
"id": 2,
"name": "something 2"
}
]
name = ""
for obj in some_list:
if obj['id'] == id:
name = obj['name']
return render_template('index.html', name=name)

Get dictionary with key/value in a list of dictionaries

I have a list of dictionaries that looks like this:
[
{
"name": "hello",
"value": "world"
},
{
"name": "foo",
"value": "bar"
}
]
What's the pythonic way of fetching the dictionary where name = "foo" from a list of dictionaries?
Assuming your list of dicts is stored as variable l, you can use next() with a generator expression like this, which returns the first dict whose name key is foo:
next(d for d in l if d['name'] == 'foo')
This will otherwise raise StopIteration if there is no dict in l with a name key that equals foo.
Try this simple example.
data = [
{
"name": "hello",
"value": "world"
},
{
"name": "foo",
"value": "bar"
}
]
for item in data:
if item['name'] == 'foo':
print(item)
Output:
{'name': 'foo', 'value': 'bar'}

Resources