You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何用Equatable包比较含无序列表的Question对象?

问题描述

我创建了一个继承Equatable的Question类,类里有个名为answers的List属性(长度固定为4,元素是String类型)。我想让两个answers元素相同但顺序不同的Question对象被判定为相等,但直接在重写的props里返回[answers]做不到这一点。相关代码和JSON响应示例如下:

Question类代码

@immutable
/// Question class to model the api response: it will be
/// used in the Presentation layer
class Question extends Equatable {
  final String question;
  final String correctAnswer;
  final List<dynamic>? answers;

  const Question({
    required this.question,
    required this.correctAnswer,
    this.answers,
  });

  @override
  List<Object?> get props => [
        question,
        correctAnswer,
        answers,
      ];
}

QuestionResponseModel类代码

@immutable
class QuestionResponseModel extends Question {
  final List<dynamic> incorrectAnswers;

  const QuestionResponseModel({
    required correctAnswer,
    required question,
    required this.incorrectAnswers,
  }) : super(
          correctAnswer: correctAnswer,
          question: question,
        );

  factory QuestionResponseModel.fromJson(Map<String, dynamic> map) {
    return QuestionResponseModel(
      question: map['question'] ?? '',
      correctAnswer: map['correct_answer'] ?? '',
      incorrectAnswers: map['incorrect_answers'] ?? [],
    );
  }

  Question toEntity() {
    return Question(
        question: question,
        correctAnswer: correctAnswer,
        answers: incorrectAnswers
          ..add(correctAnswer)
          ..shuffle());
  }

  @override
  List<Object?> get props => [
        question,
        correctAnswer,
        incorrectAnswers,
      ];
}

JSON响应示例

{
    "response_code": 0,
    "results": [
        {
            "category": "Entertainment: Books",
            "type": "multiple",
            "difficulty": "medium",
            "question": "What is the fourth book of the Old Testament?",
            "correct_answer": "Numbers",
            "incorrect_answers": [
                "Genesis",
                "Exodus",
                "Leviticus"
            ]
        }
    ]
}
解决方法

Equatable对List的相等判断是顺序敏感的——只有两个List的元素顺序完全一致,才会被判定为相等,这就是直接返回answers无法满足需求的原因。要实现无序元素的相等判断,有两种可行方案:

方案1:返回排序后的answers列表

在props里返回排序后的answers,这样不管原始顺序如何,只要元素相同,排序后的结果就一致,Equatable就能正确判定相等。

修改Question类的props:

@override
List<Object?> get props => [
      question,
      correctAnswer,
      // 先转成String列表再排序,避免dynamic类型导致的问题
      answers?.map((item) => item.toString()).toList()..sort(),
    ];

如果能确定answers里的元素都是String类型,可以简化成answers?.toList()..sort()。

方案2:将answers转为Set

Set是无序且不允许重复的集合,只要两个Set包含的元素完全相同,就会被判定为相等,刚好适配你的场景(answers是4个不重复的选项)。

修改Question类的props:

@override
List<Object?> get props => [
      question,
      correctAnswer,
      answers != null ? Set.from(answers!) : null,
    ];

额外优化提示

  1. 把Question类里的List<dynamic>? answers改成List<String>? answers,类型更明确,避免后续处理时的类型问题——毕竟你的JSON返回的答案都是字符串。
  2. QuestionResponseModel的toEntity()方法里,incorrectAnswers..add(correctAnswer)会修改原incorrectAnswers列表(List是引用类型),建议创建新列表再操作,避免产生副作用:
Question toEntity() {
  final allAnswers = List<String>.from(incorrectAnswers)
    ..add(correctAnswer)
    ..shuffle();
  return Question(
    question: question,
    correctAnswer: correctAnswer,
    answers: allAnswers,
  );
}

内容的提问来源于stack exchange,提问作者Andi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:48:25