DEV Community

Cover image for How to create your own element filter in Dart Language
Felipe Ribeiro
Felipe Ribeiro

Posted on

How to create your own element filter in Dart Language

Couple of weeks ago I was submitted for a task that demmands a way to standardize an element filter (from DIFFERENT kinds of elements). Therefore, instead of install a new dependency, I decided to create a simple algorithm that receives a generic element list and determines from which field this element should be filtered by.

Without further delay, let's analyse what I did:

List<T> filterElementsByField<T>(
  List<T> elements,
  String Function(T) fieldToCompare,
  String query,
) {
  final texts = elements
      .where(
        (e) => fieldToCompare.call(e).isNotEmpty,
      )
      .toList();


  // If nothing was typed or if is just empty, it'll return the full list content.
  if (query.isEmpty) return elements;

  return texts.where(
    (element) {

      // This is the text that is contained in the field which was parsed to the function
      final fieldText = fieldToCompare
          .call(element)
          .toLowerCase();

      final queryText = query.toLowerCase();

      if (query.contains(' ')) {
        return fieldText.contains(queryText);
      }

      // It'll try to retrieve all the content that matches with the text it contains at the parsed field. It doesn't matter if the word has blank spaces between of them.
      return fieldText.split(' ').any(
            (x) => x.startsWith(queryText),
          );
    },
  ).toList();
}

Enter fullscreen mode Exit fullscreen mode

So, let's try to apply this on a little sample code. Initially, I'll create a sample class (Pokemon) and a sample list.

class Pokemon {
   final int number;
   final String name;

   const Pokemon(
    {required this.number, required this.name,}
   );
}

List<Pokemon> pokemonList = [
    Pokemon(
     number: 1,
     name: "Pikachu",
    ),
    Pokemon(
     number: 2,
     name: "Galarian Moltres",
    ),
    Pokemon(
     number: 3,
     name: "Moltres",
    ),
    Pokemon(
     number: 4,
     name: "Charizard",
    ),
    Pokemon(
     number: 5,
     name: "Charizard X",
    ),
    Pokemon(
     number: 6,
     name: "Charizard Y",
    ),
];
Enter fullscreen mode Exit fullscreen mode

For the filtered list, we'll pass our initial list, then the class field we want to be filtered and, finally, the query we want to match with the elements from the list by attending the function algorithm.

List<Pokemon> filteredList = filterElementsByField(
   pokemonList,
   (pkmn) => pkmn.name,
   "mo"
);
Enter fullscreen mode Exit fullscreen mode

To print all the results, we'll do it as follows:

print(filteredList.map((e) => e.name).toList());
Enter fullscreen mode Exit fullscreen mode

This filtered list will retrieve for us the following result:

['Moltres', 'Galarian Moltres']

// They match with query "mo"
Enter fullscreen mode Exit fullscreen mode

Let's try a new one sample:

List<Pokemon> filteredList = filterElementsByField(
   pokemonList,
   (pkmn) => pkmn.name,
   "ch"
);
Enter fullscreen mode Exit fullscreen mode

So, this new filtered list will retrieve for us the following result:

['Charizard', 'Charizard X', 'Charizard Y']
Enter fullscreen mode Exit fullscreen mode

It'd be different if we just tried to do this:

List<Pokemon> filteredList = filterElementsByField(
   pokemonList,
   (pkmn) => pkmn.name,
   "x"
);
Enter fullscreen mode Exit fullscreen mode

The result:

['Charizard X']
Enter fullscreen mode Exit fullscreen mode

Seeing all the results, it's clear that it doesn't matter if the query matches with the first, second or another word from the same object field (as we saw like "mo" matching with "Moltres" from "Galarian Moltres" and "Moltres") and doesn't matter the word case (if it's lower, upper, alterning, capitalized...).

I highly appreciate if you read this far. If this helped you with anything, so I'm happy.

Top comments (1)

Collapse
 
epicurus1 profile image
epicurus

That was cool. thanks