FLUTTER / DART LISTS - How can you check if a sequence of elements contained in a list exists in the same order in another list?

487

I took the the last hour to solve your problem. I made it easy for you to test it and understand what is the logic behind it.

In order to use it in your code you have to put the control-flow statements into a separate function and pass the list of user input elements as well as the list of expected result elements to it.

For BOTH lists you need each word as a String, which is trimmed from all whitespaces!

I believe you are able to do that part, as described in your question already. I would deeply appreciate if you can upvote for my effort and accept the answer, if it helped you out.

EDIT: Requires an official dart package on pub.dev

Add a line like this to your package's pubspec.yaml:
dependencies:
  collection: ^1.15.0

Here is the logic, please copy & test in inside DartPad:

import 'package:collection/collection.dart';

void main() {
    
  List expectedAnswer = ["one", "two", "three"];
  List listWrongSpelling = ["oe", "two", "three"];
  List listWrongSpellings = ["oe", "twoo", "three"];
  List listWrongOrder = ["two", "one", "three"];
  List listEntirelyWrong = ["dskfrm", "twhoo", "111", "tedsf"];
  List listIdentical = ["one", "two", "three"];
   
  // FYI: Checks if there is any kind of mistake (is used below dynamically)
  Function eq = const ListEquality().equals;
   
  final result1 = eq(expectedAnswer, listWrongSpelling);  // false
  final result2 = eq(expectedAnswer, listWrongSpellings); // false
  final result3 = eq(expectedAnswer, listWrongOrder);     // false
  final result4 = eq(expectedAnswer, listEntirelyWrong);  // false
  final result5 = eq(expectedAnswer, listIdentical);      // true, the perfect answer
  
  // print(result1);
  // print(result2);
  // print(result3);
  // print(result4);
  // print(result5);
  
  
  // CHECK IF ANSWER IS PERFECT:
  bool isPerfect(List toBeChecked, List expectedResult) {
    Function eq = const ListEquality().equals;
    return eq(toBeChecked, expectedResult) ? true : false;
  }
    
  // ONLY EXECUTE OTHERS IF THERE IS AN MISTAKE:
  
  // Checks for word order mistake
  // Condition: Must contain each element with identical value, hence only order can be wrong
  bool checkOrder(List toBeChecked, List expectedElements) {
    List<bool> listOfResults = [];
    
    for (var element in toBeChecked)
    {
      bool result = expectedElements.contains(element);
      listOfResults.add(result);
    }
    
    // If one element is not in expectedElements return false
    return listOfResults.contains(false) ? false : true;
    
  }
  
  // Checks for any spelling errors
  
  bool checkSpelling(List toBeChecked, List expectedElements) {
    // Once this function gets executed there are only two errors possible:
    // 1st: Unexpected elements (e.g. an article) (and possibly spelling errors) >> return false
    // 2nd: No unexpected elements BUT spelling errors >> return true
    
    return toBeChecked.length == expectedElements.length ? true : false;
  }
  
  // FINAL RESULT
  String finalResult = "";
  
  // Please try out the other lists from above for all possible cases!
  bool isPerfectAnswer = isPerfect(listIdentical, expectedAnswer); 
  bool isWordOrderIncorrect = checkOrder(listIdentical, expectedAnswer); 
  bool isSpellingIncorrect = checkSpelling(listIdentical, expectedAnswer);
 
  if(isPerfectAnswer) {
   // The user entered the correct solution perfectly 
   finalResult = "Everything is correct!";
    
  } else if(isWordOrderIncorrect) {
    // CHECKS IF ONLY WORD ORDER IS WRONG
    // false means there are unexpected elements in the user input
    // true there are no unexpected elements, but the order is not correct, since the first check failed!
    // Is true the case, then both lists contain the same elements.

    finalResult = "Your word order is incorrect!";
    
  } else if(isSpellingIncorrect) {
    // Either unexpected elements (lenght of lists must differ) OR misspelled (same length, error in spelling)
    finalResult = "Your spelling is incorrect!";    
  } else {
    // If it gets here, the input has:
    // Unexpected elements (e.g. an article), possibly spelling errors AND possibly order mistakes 
    
    // You could check if the order is correct, but what´s the point to write complex logic for that,
    // knowing there are also unexpected elements, like additional prepositions or wrong words, in addition
    // to spelling mistakes.
    
    // Just show your user a message like this:
    finalResult = "Unfortunatelly your answer is incorrect. Try again!";   
  }
    
  // PRINT RESULT:
  print(finalResult); 
}
Share:
487
SylvainJack
Author by

SylvainJack

Updated on January 03, 2023

Comments

  • SylvainJack
    SylvainJack over 1 year

    I am working on a vocabulary quiz app (French to English / English to French). I need to check if what user types is what is expected. Example : "Une machine à laver" --> Expected answer is "A washing machine". The user can make many different sorts of mistakes such as spelling : "A watching machine", a word order mistake : "A machine washing" or a total mistake "A garden tool".

    I have managed to deal with the checking when the expected word is just one word : "un jardin : a garden".

    But with compound words, the issue of words order comes up. I split the Strings into two lists : _expectedAnswer contains the different elements of the answer : [washing,machine] _typedAnswer contains the different elements of what the user typed : [machine, washing] or [watching,machine] or [washing,machine], or [a,washing,machine] (Here, the user added an article before the noun, which shouldn't be seen as a mistake).

    At the end, the algorithm must tell the user what type of mistakes he has done :

    1. Word order mistake.
    2. Word order is correct, but one or all elements contain spelling problems.
    3. word order mistake + spelling problems
    4. completely wrong.

    For the spelling check I use the levenstein algorithm. And it is satisfactory.

    So first I thought I should check if _typedAnswer contains all the elements of _expectedAnswer. -> Should check if the sequence of elements is the same : the order is OK, and no spelling pb.

    -> Elements are all present but sequence is not respected : Problem with word order, no spelling mistakes.

    -> Elements are not present --> Then we check if "similar elements" are present (which would indicate user made a spelling mistake) .... and check the order of elements too...

    Any advice to help me work out this algorithm ?

    I have read a lot about all the functions linked to dart lists, but I have to admit, that I kinda got lost on which one would be pertinent to use...

  • SylvainJack
    SylvainJack over 2 years
    Wow !! Wasn't expecting so much :) Am looking at it in Dart Pad now, trying to understand your logic. Thanks for your help :) Will let you know as soon as I can if the whole thing works :)
  • Jahn E.
    Jahn E. over 2 years
    By the way, if you want to check for unexpected elements (e.g. an article) directly, simply add an seperate if check inside the else statement checking for that isSpellingIncorrect == false (which here means the lenght is different)
  • SylvainJack
    SylvainJack over 2 years
    the equality function comes from a package ?
  • Jahn E.
    Jahn E. over 2 years
    @SylvainJack Yes you can get it from pub.dev, but it is maintained by the dart team themselves, so you do not have to worry about support. Here is how to add it.
  • SylvainJack
    SylvainJack over 2 years
    Are you sure the checkOrder function is ok ? The "contains" function would be true whether elements are in the same sequence or not, no ?
  • SylvainJack
    SylvainJack over 2 years
    Thanks @Jahn E. I will add it. It's like an extension or the basic dart function concerning lists ?
  • Jahn E.
    Jahn E. over 2 years
    The package contains functions that operate on lists. I attached a link to my post. Look at my control flow statements, you only execute it if the order is wrong to begin with!
  • SylvainJack
    SylvainJack over 2 years