我花了一天半的时间绞尽脑汁,试图弄清楚如何为我的redux商店创建一个链式选择器,以便从一组嵌套对象中获取ID。在文档和我读过的所有例子中,我知道Iterable.map()
返回Iterable<T>
,如果你想把它当作一个列表,就需要.toList()
。返回类型List<int>
。
我不明白的是为什么我下面的选择器起作用,而另一个不起作用。我唯一能想到的是,这是一个嵌套的列表,我试图展平。我已经看到了几十个在Map中使用JSON时出现同样错误的例子,答案是使用.toList()
。
我关心的唯一原因是,我曾经使用过非常大的非常复杂的redux商店,需要多级链接-通常分为子选择器。
//models
@JsonSerializable()
class Schedule {
/* the data returned from the API is a little confusing. Each scheduled item
* has a primary and secondary task, so each team is usually listed twice for each
* task. Once the JSON is consumed and converted into models, I try to get all
* of the items task IDs so I can get more information about those tasks.
* Having come from a JSX/JavaScript background learning redux, I'm familiar
* with that style of chaining. I've tried to find information about the
* "cascade" ( .. ) operator, but information is hard to come by aside form a
* brief description. And didn't make a difference when I tried to use it.
* The reason each team is listed twice for a schedule under primaryTask and
* secondaryTask is a schedule items may have 2 teams. 99.999% of the time
* it's a single team, however, the odd time a second team will be configured
* as only a subset of the team will be assigned to the secondary task. For
* the purpose of the "get all task IDs" selector, which team that task is
* assigned to doesn't matter whatsoever.
* Example API JSON response:
[
schedule: {
teams:[ {
primaryTask:{
teamName:String,
taskId:Integer
},//primary task
secondaryTask:{
teamName:String,
taskId:Integer
}//secondary task
} //team
,... ]//teams
}//schedule
]
*/
//the map index is either "primaryTask" or "secondaryTask".
//each "Schedule" item is for a single team.
final Map<String, Team> teams;
Schedule({
required this.teams,
});
factory Schedule.fromJson(Map<String, dynamic> json) => _$ScheduleFromJson(json);
Map<String, dynamic> toJson() => _$ScheduleToJson(this);
}
@JsonSerializable()
class Team {
final int id;
final String name;
Team({
required this.id,
required this.name,
});
factory Team.fromJson(Map<String, dynamic> json) => _$TeamFromJson(json);
Map<String, dynamic> toJson() => _$TeamToJson(this);
}
//redux selector that works
List<int> getAllScheduledTeamsTaskIds( store ){
return List<int>.from(
List<List<int>>.from(
store.state.schedule
.map( ( schedule ) => [
schedule.teams['primaryTask'].id as int,
schedule.teams['secondaryTask'].id as int ]
)
)
.expand((i)=>i)
);
}
//The first selector I got to work but I didn't like it.
List<int> getAllScheduledTeamsTaskIdsMergingTwoLists( store ){
// merge two lists composed of primaryTask IDs and secondaryTask IDs
return store.state.schedule
.map( ( schedule ) => schedule.teams['primaryTask'].id as int )
.toList()
+
store.state.schedule
.map( ( schedule ) => schedule.teams['secondaryTask'].id as int )
.toList()
}
//redux selector that doesn't work
List<int> getAllScheduledTeamsTaskIdsError( store ){
return store.state.schedule
.map( ( schedule ) => [
schedule.teams['primaryTask'].id as int,
schedule.teams['secondaryTask'].id as int ]
)
.toList()
.expand((ident)=>ident)
.toList();
//error message: type '(dynamic) => (dynamic)' is not a subtype of (dynamic) => Iterable(dynamic)
}
我一直在阅读GitHub上的文档、示例和源代码,根据我所读到的内容,我所经历的行为是不期望的。但是,我找不到一个和我完全一样的例子。我不知道我错过了什么,但我相信有一些细微差别,为什么toList()
不工作,而List.from()
是。我试过cast()
、reduce()
,以及我在Iterable<T>
文档中找到的任何方法,这些方法可能会从嵌套对象列表中给予单个List<int>
,我可以将其转换为List<List<int>>
的形式。
2条答案
按热度按时间woobm2wo1#
显然,对
dynamic
值调用expand
方法会导致错误。store.state.schedule.map(...).toList()
的结果是dynamic
(尝试将其分配给变量)。为了防止错误,您可以将store.state.schedule
转换为Iterable
。请注意,我还删除了第一个
toList()
调用,因为expand
方法也适用于Iterable
。hrysbysz2#
正如上面的评论所建议的,最终我放弃了
map()
和expand()
,使用了同步生成器,如下所示。