Say each Person here has 3 key value pairs, name, age, and children. I want to iterate through the potentially endlessly nested list and create a new "Parent" model from each person. From each person model I need to create a List of Person models for each level of nesting, and if a particular person has a children, the children property on that Person model will contain a subsequent List of the correct children. (Note the main resulting nesting list of Persons is stored elsewhere in memory, I just need help creating them like in my example)
Example Structure:
Persons
- Person
- Person
- Person
- Person
- Person
- Person
- Person
Each Person above has a name, age, and children property.
ex.
{Persons:
[name: John, age: 18, children: null},
{name: Lisa, age: 32, children: [{ name: Tyler, age: 7, children: null}],
{name: Mike, age: 90, children: [{name: Derek, age 50, children:
[{name: Mary, age:25, children: null},
{name: Beth, age:16, children: null}]}]};
Recursion is not my strongest area and i'm struggling greatly with how to loop through a potentially very deep nested object. I know this is very wrong as i'm only covering the first layer of nesting. I think I should use a createPerson method like I wrote at the bottom, and use a recursive function to but I'm struggling a lot. Any insight is hugely appreciated!
ListPerson API returns Persons[] persons
private void loadPersons(String id) {
ListPersonsApi.Request request = Jso.create();
request.id = id;
dispatcher.send(ListPersonsApi.PATH, request, r-> {
for (ListPersonsApi.persons p : r.persons) {
List<Person> persons = new ArrayList<>();
PersonModel person = new Person();
person.name = p.name;
person.age = p.age;
persons.add(person);
parent.children = persons;
// Everything below this is wrong of course but its the logic I was thinking of using
List<Person> children = p.children;
while(children != null) {
for (ListPersonsApi.persons q : p.children) {
createPerson(p, q)
children = children.children;
}
})
}
private void createPerson(PersonModel parent, p) {
List<Person> persons = new ArrayList<>();
PersonModel person = new Person();
person.name = p.name;
person.age = p.age;
persons.add(person);
parent.children = persons;
}
Here is an algorithm; I haven't adapted your code since I don't have access to many of the objects.
You're right, a recursive call is what you need to accomplish this, although I'm sure there are other measures available.
Let's consider the following, a class to hold the information, call it Person
.
I've additionally provided an overridden toString
method, so we can print the information out.
static class Person {
String name;
int age;
List<Person> children;
Person(String name, int age) {
this.name = name;
this.age = age;
}
Person(String name, int age, List<Person> children) {
this.name = name;
this.age = age;
this.children = children;
}
@Override
public String toString() {
String string = "'%s', %d, ".formatted(name, age);
if (children == null)
return string + "no children";
else {
if (children.size() == 1) return string + "1 child";
else return string + children.size() + " children";
}
}
}
From here, I've created a class, call it Example
, which contains a single field, and a method.
The field is a List
of Person
, which we'll use to hold the data generated by the recursive method.
The method is a recursive function, which will traverse the given list, and add the person to the list.
Subsequently, if the person has children, they will be added to the list as well, by making a recursive call, and providing the list.
List<Person> persons = new ArrayList<>();
void persons(List<Person> list) {
for (Person person : list) {
persons.add(person);
if (person.children != null) {
persons(person.children);
}
}
}
In a separate method, I populated a list, for demonstration purposes.
It is equivalent to the example data you supplied, with the same names, ages, and children.
If I run the class and print persons
, I get the following data.
'John', 18, no children
'Lisa', 32, 1 child
'Tyler', 7, no children
'Mike', 90, 1 child
'Derek', 50, 2 children
'Mary', 25, no children
'Beth', 16, no children
So, if I'm correct, given these procedures, you could change your loadPersons
method to the following.
private void loadPersons(String id) {
ListPersonsApi.Request request = Jso.create();
request.id = id;
List<Person> list = new ArrayList<>();
dispatcher.send(ListPersonsApi.PATH, request, r -> {
for (ListPersonsApi.persons p : r.persons)
list.add(new Person(p.name, p.age, p.children));
});
persons(list);
}