I have a list of dicts. For simplicity, it contains Country/State/City/Street details
{
"addresses": [
{
"Name": "North_America",
"Id": 10001,
"Type": "Country",
"Parent_Id": 10000
},
{
"Name": "Maine",
"Id": 10011,
"Type": "State",
"Parent_Id": 10001
},
{
"Name": "Colorado",
"Id": 10012,
"Type": "State",
"Parent_Id": 10001
},
{
"Name": "Texas",
"Id": 10013,
"Type": "State",
"Parent_Id": 10001
},
{
"Name": "Augusta",
"Id": 10101,
"Type": "City",
"Parent_Id": 10011
},
{
"Name": "Portland",
"Id": 10102,
"Type": "City",
"Parent_Id": 10011
},
{
"Name": "Denver",
"Id": 10103,
"Type": "City",
"Parent_Id": 10012
},
{
"Name": "Austin",
"Id": 10104,
"Type": "City",
"Parent_Id": 10013
},
{
"Name": "Houston",
"Id": 10105,
"Type": "City",
"Parent_Id": 10013
},
{
"Name": "First_st",
"Id": 11001,
"Type": "Street",
"Parent_Id": 10101
},
{
"Name": "Second_st",
"Id": 11002,
"Type": "Street",
"Parent_Id": 10101
},
{
"Name": "First_st",
"Id": 11003,
"Type": "Street",
"Parent_Id": 10102
},
{
"Name": "Second_st",
"Id": 11004,
"Type": "Street",
"Parent_Id": 10102
},
{
"Name": "First_st",
"Id": 11005,
"Type": "Street",
"Parent_Id": 10104
},
{
"Name": "Second_st",
"Id": 11006,
"Type": "Street",
"Parent_Id": 10104
}
]
}
I want to restructure the above into a nested data structure using the Parent_Id attribute so that the final product resembles the following
Country State_1 City_1 Street_1 Street_2 City_2 Street_1 Street_2 State_2 City_1 Street_1 Street_2 City_2 Street_1 Street_2
With the data in the above format, if a new street is built, it should be possible to search this data structure, check to see if the Street name exists (in the correct City), and if it does not, add it in.
I've attempted the following
---
- name: Use groupby to create needed structure
hosts: localhost
gather_facts: false
connection: local
tasks:
- include_vars:
file: ../map.json
name: map
- name: set fact to group
set_fact:
grouped: "{{ map.addresses | groupby('Parent_Id') }}"
- name: print grouped
debug:
var: grouped
- name: set fact to re group
set_fact:
regrouped: "{{ regrouped | d([]) + [{ 'type': item.1 | map(attribute='Type')|list,
'name': item.1 | map(attribute='Name')|list|flatten }] }}"
loop: "{{ grouped }}"
- name: print regrouped
debug:
var: regrouped
The first print statement returns
"grouped": [
[
10000,
[
{
"Id": 10001,
"Name": "North_America",
"Parent_Id": 10000,
"Type": "Country"
}
]
],
[
10001,
[
{
"Id": 10011,
"Name": "Maine",
"Parent_Id": 10001,
"Type": "State"
},
{
"Id": 10012,
"Name": "Colorado",
"Parent_Id": 10001,
"Type": "State"
},
{
"Id": 10013,
"Name": "Texas",
"Parent_Id": 10001,
"Type": "State"
}
]
],
[
10011,
[
{
"Id": 10101,
"Name": "Augusta",
"Parent_Id": 10011,
"Type": "City"
},
{
"Id": 10102,
"Name": "Portland",
"Parent_Id": 10011,
"Type": "City"
}
]
],
............
............
]
The second Print isn't any better
I've also attempted piping to multiple groupby but that doesn't work, returning an error saying the second item doesn't exist
i.e.
grouped: "{{ map.addresses | groupby('Parent_Id') | groupby('Id') }}"
The function dict() is the missing part
grouped: "{{ dict(addresses|groupby('Parent_Id')) }}"
gives what you want
grouped:
10000:
- {Id: 10001, Name: North_America, Parent_Id: 10000, Type: Country}
10001:
- {Id: 10011, Name: Maine, Parent_Id: 10001, Type: State}
- {Id: 10012, Name: Colorado, Parent_Id: 10001, Type: State}
- {Id: 10013, Name: Texas, Parent_Id: 10001, Type: State}
10011:
- {Id: 10101, Name: Augusta, Parent_Id: 10011, Type: City}
- {Id: 10102, Name: Portland, Parent_Id: 10011, Type: City}
10012:
- {Id: 10103, Name: Denver, Parent_Id: 10012, Type: City}
10013:
- {Id: 10104, Name: Austin, Parent_Id: 10013, Type: City}
- {Id: 10105, Name: Houston, Parent_Id: 10013, Type: City}
10101:
- {Id: 11001, Name: First_st, Parent_Id: 10101, Type: Street}
- {Id: 11002, Name: Second_st, Parent_Id: 10101, Type: Street}
10102:
- {Id: 11003, Name: First_st, Parent_Id: 10102, Type: Street}
- {Id: 11004, Name: Second_st, Parent_Id: 10102, Type: Street}
10104:
- {Id: 11005, Name: First_st, Parent_Id: 10104, Type: Street}
- {Id: 11006, Name: Second_st, Parent_Id: 10104, Type: Street}
Example of a complete playbook for testing
- hosts: localhost
vars:
addresses:
- {Id: 10001, Name: North_America, Parent_Id: 10000, Type: Country}
- {Id: 10011, Name: Maine, Parent_Id: 10001, Type: State}
- {Id: 10012, Name: Colorado, Parent_Id: 10001, Type: State}
- {Id: 10013, Name: Texas, Parent_Id: 10001, Type: State}
- {Id: 10101, Name: Augusta, Parent_Id: 10011, Type: City}
- {Id: 10102, Name: Portland, Parent_Id: 10011, Type: City}
- {Id: 10103, Name: Denver, Parent_Id: 10012, Type: City}
- {Id: 10104, Name: Austin, Parent_Id: 10013, Type: City}
- {Id: 10105, Name: Houston, Parent_Id: 10013, Type: City}
- {Id: 11001, Name: First_st, Parent_Id: 10101, Type: Street}
- {Id: 11002, Name: Second_st, Parent_Id: 10101, Type: Street}
- {Id: 11003, Name: First_st, Parent_Id: 10102, Type: Street}
- {Id: 11004, Name: Second_st, Parent_Id: 10102, Type: Street}
- {Id: 11005, Name: First_st, Parent_Id: 10104, Type: Street}
- {Id: 11006, Name: Second_st, Parent_Id: 10104, Type: Street}
grouped: "{{ dict(addresses|groupby('Parent_Id')) }}"
tasks:
- debug:
var: grouped|to_yaml