Use a variable to sort by a key in a List<Map> instead of explicitly naming the key name - flutter

This is probably very easily answered, but I got a little stumped. Couldn't find a reference this this kind of question anywhere, which seems amazing.
I have a List<Map> and I want to sort it by the key provided through a variable instead of explicitly naming the key to sort by.
Here is what I have:
adminList.sort((a, b) => (b.sortField).compareTo(a.sortField));
AdminList is my List<Attendee> and a & b want my constructor (key) names ("firstName," "lastName," etc) and won't let me substitute a variable, as toString or anything I've tried. I want to use sortName, which might be assigned as "firstName" now, "lastName" later.

I figured this out. So technically, my named class was not a map, though it feels like one to this novice coder, and in order to access members by a string variable, I needed to create a toMap function within my class, call that, and reference my variable like so:
class AttendeeData {
final String firstName;
final String lastName;
AttendeeData({this.firstName, this.lastName,});
Map<String, dynamic> toMap() {
return {
'firstName':firstName,
'lastName:'lastName,};
}}
Now, I can define sortField, and filter by it. Changing it to lastName whenever I want.
String sortField = 'firstName';
adminList.sort(
(a, b) => (a.toMap()[sortField]).compareTo(b.toMap()[sortField]));

Related

How to retrieve the value of an object by using it's key name as a String? [duplicate]

This question already has answers here:
How to get a property by this name in String?
(2 answers)
Closed 4 months ago.
I have a typical class userData.
class userData ({K1:V1,K2:V2,K3:V3})
But i want to retrieve the data from several of them at the same time.
userData1 {K1:V1,K2:V2,K3:V3}
userData2 {K1:V4,K2:V5,K3:V6}
userData3 {K1:V7,K2:V7,K3:V8}
instead of using typical direct way:
print ("${userData1.K1} ${userData2.K1} ${userData3.K1}") ;
I want to access the data in an indirect method by using the key name as a String. Something like this:
String MyKey = 'K1';
print ("${userData1[MyKey]} ${userData2[MyKey]} ${userData3[MyKey]}") ;
Is there a way to retireve the values by using the key name as a String?
Thanks in advance for your help
Your question is unclear.
You may be looking for __getitem__. https://docs.python.org/3/library/operator.html#operator.getitem
Consider
d = dict(a=1, b=2)
When you ask for d['a'], you are calling d.__getitem__('a') behind the scenes.
There is an opportunity for your container class to inherit from dict,
and override __getitem__, if you wish to add behavior like logging,
or something fancier.
This is similar to the str() protocol that you likely are already familiar with.
Overriding __str__ will change the behavior of str(...)
and things that call it, such as format(...).
You should certainly review the getattr documentation.
When you write some code that addresses the need to your liking,
do post it here. https://stackoverflow.com/help/self-answer
Here is one solution that worked for me by creating a new dynamic in my class:
class MyClass{
....
dynamic getProp(String key) => <String, dynamic>{
'K1': K1,
'K2': K2,
'K3': K3,
}[key].toString();
}
}
With this i can retrieve with this line:
print(MyClass.getProp("K1"));
And so to get the data from my array, it work like this:
userData1 {K1:V1,K2:V2,K3:V3}
userData2 {K1:V4,K2:V5,K3:V6}
userData3 {K1:V7,K2:V7,K3:V8}
myKey = "K1";
print ("${userData1.getProp("K1")} ${userData2.getProp("K1")} ${userData3.getProp("K1")}"); // prints "V1 V4 V7"

How to avoid typing incorrect serialization name when updating a property from a database?

I'm using Firestore database and i want to update some fields from a document.
var updateFields = {
"completedByUid": authRepo.getUID(),
"completed": currentTime,
};
return await docRef.update(updateFields);
Instead of typing the properyName manually how can i get the name directly from an object Object, and by this avoiding typing it incorrectly or outdated.
Let's say i have an object like:
#JsonSerializable()
class OrderModel {
String? completedByUid;
String? completed;
}
and i want to get the serialization name something like:
var updateFields = {
OrderModel.completedByUid: authRepo.getUID(),
or
var updateFields = {
order.completedByUid.properyName: authRepo.getUID(),
Normally this would be a use for reflection but that might be overkill.
I think the design pattern you could use is a constant that you use to both set and read the values, like so:
const String ORDER_MODEL_COMPLETED_BY_UID_PROPERTY = "completedByUid";
This doesn't exactly guarantee a match if, for example, some existing data is present and may have a name mismatch.
For an answer based on reflection, see this answer.

json_serializable not generating code for final fields and getters

This is my class:
#JsonSerializable()
class Foo {
final int a = 0;
int get b => 42;
}
The generated code doesn't include any of the a or b field:
Foo _$FooFromJson(Map<String, dynamic> json) => Foo();
Map<String, dynamic> _$FooToJson(Foo instance) => <String, dynamic>{};
Note: Please don't write solutions for doing something like Foo(this.a) or Foo() : a = 0 etc. I need to keep my structure as it is.
Simple answer - this won't be possible as this is done intentionally by design.
If adjusting your model structure is out of the question, you can try manual conversion or a mix of these two.
After encountering the same issues myself, not long ago, I opted in for manual converting my models - and also a combination of two in some cases.
With #JsonSerializable, you can make use of the from/to generated methods, and then in addition, manually convert your final and getter fields.
Another option you can try, at least for the getter fields, is making use of #JsonSerializable(crateFactory: false). This will indicate the engine to convert getters as well.
I suggest reading Flutter JSON Docs in detail and figuring out what will suit you the most, depending on your models, what you want, or what you can compromise on.
Worth reading the Github thread on getter conversion.
There's no out of the box workaround for final fields though, but as per this Github thread on final fields, PRs are welcome :)
If you want easier json parsing, use Dart Data Class Generator extension in VS Code.
I think since a is final, it is considered a constant and not variable and b is a getter and not a variable, there are no variables (fields) for json_serializable to generate code for.
You need to add a default constructor before json_serializable can run. Since you have no fields, you wil have an empty constructor and empty methods generated.
class Foo {
final int a = 0;
int get b => 42;
const Foo();
factory Foo.fromJson(Map<String, dynamic> json) => Foo();
Map<String, dynamic> toJson() => <String, dynamic>{};
}

Iterate over _InternalLinkedHashMap not working

I'm trying to iterate over the following data structure: {String: [{String, List<SomethingResponse>}]} where SomethingResponse = {String: dynamic}). I created this model:
class SomethingsResponse {
final Map<String, List<SomethingResponse>> SomethingsResponse;
SomethingsResponse({this.SomethingsResponse});
factory SomethingsResponse.fromJson(data) {
return SomethingsResponse(SomethingsResponse: data.map<String, List<SomethingResponse>>((String key, dynamic value) {
final dataFromCategory = List<SomethingResponse>.from(value.map((x) => SomethingResponse.fromJson(x)));
return MapEntry(key, dataFromCategory);
}));
}
}
When I try getting the keys like this: data.somethingsResponse.toList(), I get an error saying:
Class '_InternalLinkedHashMap<String, List>' has no instance method 'toList'.
I can't iterate over it or really get any kind of data out of it. What am I doing wrong and how can I fix it? I have a feeling the issue is at this line return MapEntry(key, dataFromCategory);, but I tried creating a Map a couple of different ways, and none worked.
If you consult the documentation for Map, you will see that it does not derive from Iterable and therefore cannot be directly iterated over. I presume that this is because it's not obvious what you want to iterate over: keys, values, or key-value pairs?
If you want to iterate over keys, use Map.keys. (In your case: data.somethingsResponse.keys.toList())
If you want to iterate over values, use Map.values.
If you want to iterate over key-value pairs (i.e. MapEntry objects), use Map.entries.

Please help me understand fromMap and toMap from this code?

I got this code from the internet and I can not seem to understand it or find anything on the internet for it.
In the code below toMap is a method that returns 2 items, How is that possible?
And what is fromMap, is it a user created method? I thought methods used {} or => so it is a bit confusing.
Also, what is the key here for the Map? Can the map only store 2 categories of items? One is the key and the other is the value. Or it can have one key but multiple categories of values.
For example, there might be a single unique key, which could help take out the task title, time, reminder data, notes, etc as values of the map.
class Task {
String title;
bool completed;
Task({
this.title,
this.completed = false,
});
Task.fromMap(Map<String, dynamic> map): title = map['title'],completed = map['completed'];
updateTitle(title) {
this.title = title;
}
Map toMap() {
return {
'title': title,
'completed': completed,
};
}
}
In the code below toMap is a method that returns 2 items, How is that
possible?
No, it returns a Map (with two items). More about maps can be found here.
And what is fromMap, is it a user created method? I thought methods
used {} or => so it is a bit confusing.
Task.fromMap(Map<String, dynamic> map) is called "named constructor". The : title = map['title'],completed = map['completed'] part is initializer list
My understanding is;
In fromMap, you retrieve the title and completed from some map, and save it in your local variables.
In the toMap you take the saved values in your local variables and can return a Map.
The key is whatever you put you chose it to be, but here you chose one key to be titleand one to be completed.
Does this help you?
First of all we discuss about FormMap So what is fromMap()?
whenever you have any api and at firetime you will get json format so when you want to convert that data into any class format then you have to do like
Map temp = json.decode(response.body);
so your function can understand map key and retrieve that value and set in class local variable
and now Second point is toMap So what is toMap()?
Whenever you want to post something into api or somewhere you have map data so you can post in api
like
Abc a = Abc(name:"hari",address:"india");
a.toMap();