首页 > 解决方案 > 如何将列表中的对象列表组合到 Dart 中的新列表?

问题描述

这个问题经常使用“列表”这个词,如果没有进一步的解释,可能会令人困惑,所以让我给你一个简单的例子来说明我的意思:

假设我有一个名为City. 它包含一个List<House> houses. 并且每一个都House包含一个List<Person> persons包含所有居住在建筑物中的人。

所以要获得住在房子里的人的名单,5我必须使用city.houses[5].people. 在这种情况下,获取居住在城市本身的所有人名单的最有效方法是什么?

我应该在课堂上创建一个单独的列表City并将所有人都添加进去吗?我是否应该getPeople在类中实现一个方法,该方法City使用一个 for 循环,将每个建筑物中的人员添加到一个新列表并每次都返回它?或者在 Dart 中是否有更有效的方法来实现这一点。

任何建议将不胜感激:)

标签: listdart

解决方案


您正在寻求最有效的方法,以及如何为其设计 API。这两个是不同的问题。

收集居住在房屋中的人的最有效方法是以下之一:

 city.houses.expand((h) => h.people);
 // or
 [for (var h in city.houses) ...h.people]

如果一个人可以住在多个房子里,您可能希望将其设置为一组而不是列表。

从 API 设计的角度来看,“所有房子里的所有人”的属性可以作为city. 在那种情况下,我可能会成功city.population,所以声明为List<People> get population => ...;.

您可以选择在每次请求时计算列表,在第一次请求时缓存列表,或者在创建城市对象时创建它——假设它是一个不可变的城市。如果可以修改城市对象,或者更糟糕的是,可以修改单个房屋,那么当发生任何更改时,您需要使缓存无效。这相当复杂且容易出错,我可能会在每次要求时都计算结果。如果您有一种有效的方法来检测突变并且您实际上希望在突变之间多次查询总体,则仅缓存或预先计算列表。

另一个因素是 getter 的使用频率。如果它经常发生,那么缓存或预计算绝对是要走的路。如果非常罕见,那么每次计算它不会是一个很大的开销。如果它非常罕见,那么该属性可能根本不值得放置city,您可以只提供一个单独的静态辅助函数populationOf(City city) => ...。或者不是,因为对于碰巧需要整个人口的人来说,上面的表达式并不难写。

所以,如果缓存:

class City { 
  ...
  List<People>? _population;
  ...
  List<People> get population => 
      _population ??= [for (var h in houses) ...h.people];
}

如果预计算:

class City {
  final List<People> population;
  ...
  City(this.houses, ...) : population = [for (var h in houses) ...h.people];
  ...
}

推荐阅读