Query a list of list of objects in Dart? - flutter

I need to get all the details of a specific client:
I have a list of list for the details of all the clients:
List<List<ClienteDetails>> _listaClientDetails = List<List<ClienteDetails>> ();
I want to get the details for a specific client, and I'm trying to do it by using this code: I
var result = _listaProductosFactura.where((detailsList) => detailsList.where((cliente) => cliente.id == id)).toList();
But this code is wrong. "The return type 'Iterable' isn't a 'bool', as required by the closure's context."
Does someone know what would be the right code?

The problem with your code is that this part of it doesn't return a boolean value :
detailsList.where((cliente) => cliente.id == id)
it returns an iterable from your inner list which is not a boolean.
So the first "where" method cannot return an iterable as it doesn't have a boolean result
var result = _listaProductosFactura.where((detailsList) => //you must have a boolean result here not an iterable
//but detailsList.where((cliente) => cliente.id == id) gives you an iterable
You can do something like this to get the result you want:
List<List<ClienteDetails>> _listaClientDetails = List<List<ClienteDetails>> ();
var result;
for(List<ClienteDetails> clienteDetails in _listaClientDetails){
result = clienteDetails.where((cliente)=>cliente.id == id).toList();
//goes through the inner list and get the element where cliente.id == id
}

Related

Null-aware .firstWhere, .singleWhere, .lastWhere in Dart's List?

I often use .firstWhere((E element) -> bool) -> E in my project. When porting it to support null safety I couldn't cleanly handle a scenario when an element is not found in a List instance.
.firstWhere, .singleWhere and .lastWhere returns E, not E? so when handling a case when a List does not contain required element there's no other way to return null other than casting a whole list from eg. List<String> to List<String?> which makes testing function worried about each element being potentially null, which it can't be. Before null safety I was able to just use orElse: () => null but with null safety orElse have to return element of type E so troublesome casting is required.
Do I have to have a null substitute for each type to use in orElse or are there other methods to make list checking support missing element scenario with null?
You can just use firstWhereOrNull which should work exactly as you expect.
The solution would be to create an extension on the Iterable type:
extension IterableModifier<E> on Iterable<E> {
E? firstWhereOrNull(bool Function(E) test) =>
cast<E?>().firstWhere((v) => v != null && test(v), orElse: () => null);
}
Then use it like this:
final myList = <String?>['A', 'B', null, 'C'];
String? result = myList.firstWhereOrNull((e) => e == 'D');
print(result); // output: null
result = myList.firstWhereOrNull((e) => e == 'A');
print(result); // output: "A"
Try the full example on DartPad

Filter list with whereIn condition in Flutter?

This code sample works fine.
var box = await Hive.openBox<MainWords>('mainWords');
box.values.where((item) {
return item.category == "6" || item.category == '13';
}).toList();
I am trying to filter a list with whereIn condition but it must filter like
List<String> categoryList = ['6', '13'];
var box = await Hive.openBox<MainWords>('mainWords');
box.values.where((item) {
return item in categoryList; // just an examle
}).toList();
How can i achive this?
You should not use the keyword in but the method contains to check if your item exists inside categoryList. Moreover you cannot compare values of different types, I'm seeing that you are returning with box.values an Iterable<MainWords>.
I don't know the content of this class but the item variable is of type MainWords and so it cannot be compared with a String object directly.
I am supposing that you have some access to a String value from your class MainWords so you will need to compare this value with your list.
Code Sample
List<String> categoryList = ['6', '13'];
var box = await Hive.openBox<MainWords>('mainWords');
// As I don't know what are MainWords' properties I named it stringValue.
box.values.where((item) => categoryList.contains(item.stringValue)).toList();

Dart / Flutter : Waiting for a loop to be completed before continuing... (Async Await?)

I have a function which creates a sublist from a large(very large list). After creating this list, the function goes on treating it (deleting duplicates, sorting...).
As long as the list was not too big, it worked fine. But now, I get "The Getter length was called on null". I suppose, it's because the second part of the function (after the loop) starts before the sublist is completed... so it doesn't work...
How can we force the function to wait for the loop to be over to continue the rest of the treatment ?
Is it with Async /Await ? Or can we do something like "While... something is not over...", or "As soon as something is done... do that" ? (My suggestions might be naive, but I am a beginner...)
Here is the code :
List themeBankFr() {
List<Map> themeBankFr = [];
for (Word word in wordBank) {
for (Thematique wordTheme in word.theme) {
themeBankFr.add({
'themeFr': wordTheme.themeFr,
'image': wordTheme.image,
});
}
}
// convert each item to a string by using JSON encoding
final jsonList = themeBankFr.map((item) => jsonEncode(item)).toList();
// using toSet - toList strategy
final uniqueJsonList = jsonList.toSet().toList();
// convert each item back to the original form using JSON decoding
final result = uniqueJsonList.map((item) => jsonDecode(item)).toList();
// sort the list of map in alphabetical order
result.sort((m1, m2) {
var r = m1['themeFr'].compareTo(m2['themeFr']);
if (r != 0) return r;
return m1['image'].compareTo(m2['image']);
});
return result;
}
i think i have a good answer that may helps you and it will as following
first create another function to do the work of for loops and this function returns a future of list that you need like below
Future<List<Map>> futureList(List wordBank){
List<Map> themeBankFr = [];
for (Word word in wordBank) {
for (Thematique wordTheme in word.theme) {
themeBankFr.add({
'themeFr': wordTheme.themeFr,
'image': wordTheme.image,
});
}
}
return Future.value(themeBankFr);
}
after that you can use this function inside your code and use it as async await and now you will never run the below lines before you return this array like below
List themeBankFr() async {
List<Map> themeBankFr = await futureList(wordBank);
// convert each item to a string by using JSON encoding
final jsonList = themeBankFr.map((item) => jsonEncode(item)).toList();
// using toSet - toList strategy
final uniqueJsonList = jsonList.toSet().toList();
// convert each item back to the original form using JSON decoding
final result = uniqueJsonList.map((item) => jsonDecode(item)).toList();
// sort the list of map in alphabetical order
result.sort((m1, m2) {
var r = m1['themeFr'].compareTo(m2['themeFr']);
if (r != 0) return r;
return m1['image'].compareTo(m2['image']);
});
return result;
}
i think this will solve your problem and i hope this useful for you

CQLINQ for list of methods returning a specific type or interface?

What is the CQLINQ to get list of methods returning a (compatible) specific type or interface?
You can get inspiration from such query:
let listOfT = ThirdParty.Types.WithFullName(
"System.Collections.Generic.IList<T>").Single()
let compatibleTypes = listOfT.TypesThatImplementMe.Concat(listOfT)
from m in Methods.Where(m => m.ReturnType != null && compatibleTypes.Contains(m.ReturnType))
select new { m, m.ReturnType }

Getting the previous element of a IOrderedEnumeration

I have a enumeration of objects :
public IOrderedEnumerable<RentContract> Contracts {
get { return RentContracts.OrderByDescending(rc => rc.DateCreated); }
}
I have to compare a given RentContract instance with its previous RenContract instance on the list to highlight changes between the two objects, which is the most correct method to get the previous element ?
This is not possible directly. You can do it like this:
var input = new SomeClass[10]; //test data
var zipped = input.Zip(new SomeClass[1].Concat(input), (a, b) => { a, b });
var result = zipped.Where(x => x.b == null || x.a.DateCreated < x.b.DateCreated.AddHours(-1)); //some example
This solution is zipping the sequence with itself, but offset by one null element.