Colin Ricardo
Colin Ricardo

Reputation: 17239

Getting index from list while iterating

I have the following code:

const List<Map> QUESTION_LIST = [
  {
    "questionText": "What's your name?",
    "answers": ["One", "Two", "Three"],
    "correctAnswerIndex": 1
  },
];


  List<Widget> buildQuestionAndAnswers() {
    if (_questionIndex == QUESTION_LIST.length - 1) {
      return ([buildFinalScreen()]);
    }

    Map currentPair = QUESTION_LIST[_questionIndex];
    String currentQuestion = currentPair["questionText"];
    List<String> currentAnswers = currentPair["answers"];
    int currentCorrectAnswerIndex = currentPair["correctAnswerIndex"];

    return ([
      Question(questionText: currentQuestion),
      ...currentAnswers
          .asMap()
          .map(
            (i, answer) => Answer(
              text: answer,
              onPress: () {
                _onAnswerPress(i, currentCorrectAnswerIndex);
              },
            ),
          )
          .values
          .toList()
    ]);
  }

What I want to do is get the index of the button that is pressed so that it can be compared with the correctAnswerIndex.

With the above code I get the error:

The return type 'Answer' isn't a 'MapEntry', as defined by anonymous closure.dart(return_of_invalid_type_from_closure)

What is the correct way to fix this?

Upvotes: 0

Views: 129

Answers (1)

Abion47
Abion47

Reputation: 24616

When you use map on a Map, you are expected to return an instance of MapEntry. In your case, you are returning an Answer, so that is the cause of your error.

In reality, your chain of methods starting with asMap is all unnecessary. Either use a C-like for loop:

final answerList = <Widget>[Question(questionText: currentQuestion)];
for (int i = 0; i < currentAnswers.length; i++) {
  answerList.add(Answer(
    text: currentAnswers[i],
    onPress: () => _onAnswerPress(i, currentCorrectAnswerIndex),
  ));
}
return answerList;

or an incrementing index variable together with a closure:

int index = 0;
return <Widget>[
  Question(questionText: currentQuestion),
  for (var answer in currentAnswers)
    createAnswerWidget(answer, index++),
];

...

Widget createAnswerWidget(String answer, int idx) {
  return Answer(
    text: answer,
    onPress() => _onAnswerPress(idx, currentCorrectAnswerIndex),
  );
}

EDIT: If you really want the second option to be a "single line" type of solution, you could combine the spread operator, a generated list, and a map method to eliminate the need to maintain an external index:

return <Widget>[
  Question(questionText: currentQuestion),
  ...List.generate(currentAnswers.length, (i) => i)
         .map((i) => Answer(
           text: currentAnswers[i],
           onPress: () => _onAnswerPress(i, currentCorrectAnswerIndex),
         ))
         .toList(),
];

Personally I wouldn't recommend this solution as it's less efficient and performant, plus I don't think it's all that readable especially for others who don't already know what it's supposed to do.

Upvotes: 1

Related Questions