简体   繁体   English

如何清理一个复杂的.map function?

[英]How do I clean up a complicated .map function?

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.我试图了解如何使用Equatable.copyWith方法更新深度嵌套的数据,并且在这样做的过程中,我制作了一个复杂的.map function。

Problem:问题:

Ideally, I would like to use some iterative functional programming technique to simplify the getNewHierarchy() function;理想情况下,我想使用一些迭代函数式编程技术来简化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.').但是,它必须导致复杂的.map function (在最小可行代码中标记为“//TODO:我想清理此方法并使其不那么复杂。”)。 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.尽我所能,我找不到一种方法来降低这个 function 的复杂性,使用复合设计模式或其他函数式编程技术而不破坏它。

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.在 main 方法中,我将一个深度嵌套的数据 object 拼凑在一起,然后我可以“getNewHierarchy()”重命名选择的嵌套 object。 In this case, I have randomly inserted an object of the nested class for example purposes only.在这种情况下,我随机插入了嵌套 class 的 object,仅用于示例目的。 The objective is to make the getNewHierarchy() function less complex without breaking my code.目标是在不破坏我的代码的情况下使getNewHierarchy() function 不那么复杂。 This method maps through the NestedClass object looking for the object of a class and changes it's name.此方法通过 NestedClass object 映射,查找 class 的 object 并更改其名称。 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.如果它没有找到 object,它会进入寻找 class 的孩子列表,并在找到正确的 object 时更改其名称。 This code is very messy.这段代码非常混乱。

Question:问题:

How can I simplify the complex .map function that works with deeply nested data?如何简化处理深度嵌套数据的复杂.map function?

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!先感谢您!

Yikes, this would be much easier to solve if you, at all, ever, explained what the heck the getNewHierarchy function is supposed to do.哎呀,如果你曾经解释过 getNewHierarchy function 到底应该做什么,这将更容易解决。

From what I can tell, you pass it a new name, an old version and a new version, then proceed to replace the new version's children with the old version's, but before doing that, you check each of the children against the new class and if they match, you change their name, and if they don't you keep it?据我所知,您传递了一个新名称,一个旧版本和一个新版本,然后继续用旧版本替换新版本的孩子,但在此之前,您检查每个孩子与新的 class 和如果他们匹配,你改变他们的名字,如果他们不,你保留它?

How about something like this?这样的事情怎么样?

NestedClass getNewHierarchy(String newName, NestedClass newValue, NestedClass oldValue) {
  return newValue.copyWith(
    name: oldValue == newValue ? newName : oldValue.name,
    children: oldValue.children.map((v) => getNewHierarchy(newName, v, newValue)).toList(),
  );
}

Also from what I can tell, your data is never equal?另外据我所知,您的数据永远不相等? Is that just cuz this is an example?这只是因为这是一个例子吗? You already know you want to edit the greatGrandParents.children[0].children[1];您已经知道要编辑greatGrandParents.children[0].children[1]; child, so why don't you update it directly???孩子,那你为什么不直接更新呢???

Also if you are gonna change both the name and children, you know, the two only things in your class, there is no use for a copyWith call, you can just use a normal constructor:另外,如果您要同时更改名称和孩子,您知道,class 中仅有的两件事, copyWith调用没有用,您可以使用普通的构造函数:

return NestedClass(
    name: oldValue == newValue ? newName : oldValue.name,
    children: oldValue.children.map((v) => getNewHierarchy(newName, v, newValue)).toList(),
  );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM