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();
}
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",
),
];
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"
);
To print all the results, we'll do it as follows:
print(filteredList.map((e) => e.name).toList());
This filtered list will retrieve for us the following result:
['Moltres', 'Galarian Moltres']
// They match with query "mo"
Let's try a new one sample:
List<Pokemon> filteredList = filterElementsByField(
pokemonList,
(pkmn) => pkmn.name,
"ch"
);
So, this new filtered list will retrieve for us the following result:
['Charizard', 'Charizard X', 'Charizard Y']
It'd be different if we just tried to do this:
List<Pokemon> filteredList = filterElementsByField(
pokemonList,
(pkmn) => pkmn.name,
"x"
);
The result:
['Charizard X']
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)
That was cool. thanks