Introduction:
I am trying to get my head around how to update deeply nested data using Equatable and .copyWith methods and in doing so, I have made a complex .map function.
Problem:
Ideally, I would like to use some iterative functional programming technique to simplify the getNewHierarchy() function; but the solution eludes me. The minimal code works as expected, and I can update the deeply nested data in my code. But, it has to lead to a complex .map function (labelled in the minimum viable code '//TODO: I would like to clean this method and make it less complex.'). Try as I might, I cannot find a way to reduce the complexity of this function using a composite design pattern or another functional programming technique without breaking it.
Objective:
This is a remake of a project that I am working on that has a bigger purpose than the question. It is the most basic of minimal viable code for the questions. In the main method, I patch together a deeply nested data object, and then I can 'getNewHierarchy()' to rename the nested object of choice. In this case, I have randomly inserted an object of the nested class for example purposes only. The objective is to make the getNewHierarchy() function less complex without breaking my code. This method maps through the NestedClass object looking for the object of a class and changes it's name. If it does not find the object, it goes into the list of children looking for the class and changes its name when it finds the correct object. This code is very messy.
Question:
How can I simplify the complex .map function that works with deeply nested data?
My code:
// add equatable: ^2.0.5 to pubspec.yaml
import 'package:equatable/equatable.dart';
void main() {
/// Minimum viable code to reproduce the issue
var greatGrandParents =
const NestedClass(name: 'Great Grand Parents', children: [
NestedClass(name: ' Grand Parents 1', children: [
NestedClass(name: ' Parents 1', children: [
NestedClass(name: ' Children 1', children: []),
NestedClass(name: ' Children 2', children: []),
]),
NestedClass(name: ' Parents 2', children: [
NestedClass(name: ' Children 3', children: []),
NestedClass(name: ' Children 4', children: []),
]),
NestedClass(name: ' Parents 3', children: [
NestedClass(name: ' Children 5', children: []),
NestedClass(name: ' Children 6', children: []),
])
]),
NestedClass(name: ' Grand Parents 2', children: [])
]);
print('=====================');
print('Original: ');
greatGrandParents.printChildrenNames();
print('=====================');
print('Updated: ');
final childToBeUpdated = greatGrandParents.children[0].children[1];
final updatedHierarchy =
getNewHierarchy('***George***', childToBeUpdated, greatGrandParents);
updatedHierarchy.printChildrenNames();
print('=====================');
}
// Model
class NestedClass extends Equatable {
final String name;
final List<NestedClass> children;
const NestedClass({
required this.name,
required this.children,
});
printChildrenNames() {
print(name);
for (var child in children) {
child.printChildrenNames();
}
}
NestedClass copyWith({
String? name,
List<NestedClass>? children,
}) {
return NestedClass(
name: name ?? this.name,
children: children ?? this.children,
);
}
@override
List<Object> get props => [name, children];
}
//TODO: I would like to clean this method and make it less complex.
NestedClass getNewHierarchy(
String newName, NestedClass person, NestedClass old) {
NestedClass copiedPerson = person.copyWith(
children: old.children
.map((e) => e.copyWith(
name: e == person ? newName : e.name,
children: e.children
.map((e) => e.copyWith(
name: e == person ? newName : e.name,
children: e.children
.map(
(e) =>
e == person ? e.copyWith(name: newName) : e,
)
.toList(),
))
.toList(),
))
.toList(),
);
return copiedPerson;
}
Appreciate if someone can advise. Thank you in advance!