How would you find a certain map entry by a specific value? - flutter

Given the following map:
"user":
{
"userid":0,
},
"appData":{
"title":"Test",
"pages":1,
"posts":[
{
"postid":27979530,
"text":Test,
},
{
"postid":7732445,
"text":Test123,
},
{
"postid":9463254,
"text":Test568,
},
]
}
Given that map I want to try to find the entry for postid 7732445 so I can return the text value of Test123
What is the best way of doing something like that?

Given that
final Map<String, dynamic> json = {
"user": {
"userid": 0,
},
"appData": {
"title": "Test",
"pages": 1,
"posts": [
{
"postid": 27979530,
"text": "Test",
},
{
"postid": 7732445,
"text": "Test123",
},
{
"postid": 9463254,
"text": "Test568",
},
]
}
};
you could do this search by doing
json["appData"]["posts"]
.firstWhere(
(item) => item["postid"] == 7732445,
orElse: () => <String, Object>{},
)["text"]
Because of the orElse, this will return null if not found.

Related

searching a map in dart and returning all values matching search

I have a map, with multiple layers, some of the layers have an events field which may contain 0 or more event listings inside of it.
Some of events are nested deeper into the map, while others are closer to the top layer.
Here is what the graphql query result looks like:
{
"data": {
"users": [
{
"id": 16,
"friends": [
{
"senderId": 16,
"receiverId": 17,
"userByReceiverid": {
"id": 17,
"events": [],
"friends": [
{
"receiverId": 14,
"userByReceiverid": {
"id": 14,
"events": [
{
"id": 3,
"photoUrl": "none",
"name": "hello",
"date": "1982-06-27",
"startTime": "01:00:00+00",
"endTime": "02:00:00+00",
"fee": "$2.00",
"maxNumber": 10,
"ageRestriction": "none",
"about": "amazing",
"allowShare": false,
"private": false,
"timestamp": "2021-06-26T17:57:13.224383+00:00",
"senderId": 14
}
]
}
},
{
"receiverId": 20,
"userByReceiverid": {
"id": 20,
"events": []
}
}
]
}
}
],
"friendsByReceiverid": [
{
"senderId": 20,
"receiverId": 16,
"user": {
"id": 20,
"events": [],
"friendsByReceiverid": [
{
"receiverId": 20,
"user": {
"id": 14,
"events": [
{
"id": 3,
"photoUrl": "none",
"name": "hello",
"date": "1982-06-27",
"startTime": "01:00:00+00",
"endTime": "02:00:00+00",
"fee": "$2.00",
"maxNumber": 10,
"ageRestriction": "none",
"about": "amazing",
"allowShare": false,
"private": false,
"timestamp": "2021-06-26T17:57:13.224383+00:00",
"senderId": 14
}
]
}
},
{
"receiverId": 20,
"user": {
"id": 17,
"events": []
}
}
]
}
}
]
}
]
}
}
I want to search the Map and make a list that contains all the events that are unique, so no duplicates if possible.
How would I go about pulling out only the events field from a map at any given point?
Essentially what you need is a function (visitObject) that goes through each key of the a Map and recursively calls itself till all properties have been checked.
The function should also check for the possible types it can operate on and handle the data so you can call the visitObject function with the right arguments.
I believe the right data structure here would be a Set. In dart as Set is defined as A collection of objects in which each object can occur only once.
However Set a set falls back to the dart method of equality which is the == operator, so you would either need to use a calls for Events or use a package like BuiltValue which will generate the == operator for your value types.
Here is an example that can help you get started, I have left equality checking for you to determine what best and how you want to apply it.
final Set<Map<String, dynamic>> items = {};
void main() {
visitObject(data);
}
void visitObject(object) {
if (object is List) {
for(dynamic item in object) {
visitObject(item);
}
} else if (object is Map) {
if (object.containsKey('events')) {
var _events = object['events'];
if (_events is List && _events.isNotEmpty) {
_events.forEach((e) {
if (!items.contains(e)) {
items.add(e);
}
});
}
}
for (dynamic item in object.values) {
visitObject(item);
}
}
}
Additional Reading for equality:
==Operator
hashCode
BuiltValue

unable to retrieve object inside object

I am new to flutter . i am trying to fetch responnse from api . i am getting response as 200 but unable to retreive particular object inside it .
please have a look at a model class below and suggest me what wrong i am doing
class Response {
bool success;
List<dynamic> errors;
List<CourseParent> courses;
Batches coursedetail;
Response({this.success,this.errors,this.courses,this.coursedetail});
factory Response.fromJson(Map<String, dynamic> map) {
return Response(
errors: map['errors'],
success: map['success'],
courses: map['courses'] != null
? map['courses'].map<CourseParent>((json) => CourseParent.fromJson(json)).toList()
: null,
coursedetail: map['courseDetails'] != null
? map['courseDetails'].map<Batches>((json) => Batches.fromJson(json))
: null,
);
}
Map<String, dynamic> toJson() {
return {"success": success, "errors": errors, "courses": courses, "courseDetails" : coursedetail};
}
#override
String toString() {
return 'Response{ success: $success, errors: $errors , courses: $courses, courseDetails: $coursedetail }';
}
}
List<Response> profileFromJson(String jsonData) {
final data = json.decode(jsonData);
return List<Response>.from(data.map((item) => Response.fromJson(item)));
}
Response responseFromJson(String str) {
final jsonData = json.decode(str);
print("##-response"+jsonData.toString());
return Response.fromJson(jsonData);
}
String responseToJson(Response data) {
final jsonData = data.toJson();
print("##--encoding"+json.encode(jsonData));
return json.encode(jsonData);
}
i am getting the error as below
NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance method 'map' with matching arguments.
Acutall expected json is below
{
"success": true,
"courseDetails": {
"courseId": 34,
"title": "Taxi Drivers Qualification Program",
"code": "TX001",
"image": "uploads\\9e5dba0e-0e25-4247-a3fa-a2a404aadacd.jpg",
"target": 0,
"batches": [
{
"batchId": 41,
"courseId": 34,
"instructorId": 22,
"venueId": 1,
"startDate": "2021-01-03T00:00:00",
"endDate": "2021-01-17T00:00:00",
"startTime": "2021-01-03T09:17:00",
"endTime": "2021-01-03T12:17:00",
"capacity": 25,
"gender": 2,
"instructor": [
{
"instructorId": 22,
"civilId": "931285",
"forceId": "123",
"title": 15,
"fullname": "Mansoor Abdulrahim Al Rasbi",
"email": "steve.jobs#apple.com",
"mobile": "99699633",
"type": 1
}
],
"venue": [
{
"venueId": 1,
"name": "B22",
"branchId": 1,
"branch": [
{
"branchId": 1,
"name": "Head Quarters - Muscat",
"capacityTheoretical": 175,
"capacityPractical": 125
}
],
"bookingFees": 25
},
{
"venueId": 21,
"name": "Meetings Hall",
"branchId": 1,
"branch": [
{
"branchId": 1,
"name": "Head Quarters - Muscat",
"capacityTheoretical": 175,
"capacityPractical": 125
}
],
"bookingFees": 20
},
{
"venueId": 41,
"name": "Store Muscat Branch",
"branchId": 1,
"branch": [
{
"branchId": 1,
"name": "Head Quarters - Muscat",
"capacityTheoretical": 175,
"capacityPractical": 125
}
]
}
]
}
]
}
}
You need to parse courseDetails directly, it is an object, not Map or List:
coursedetail: map['courseDetails'] != null ? Batches.fromJson(map['courseDetails']) : null;

How to query objects from a set of key IDs in Firebase?

Consider the following data structure:
{
"company": {
"idCompany1": {
"data": {
"address": "",
"companyName": "Company 1",
"logo": "assets/Logo1.png",
"nit": "",
"phone": ""
}
},
"idCompany2": {
"data": {
"address": "",
"companyName": "Company 2",
"logo": "assets/Logo2.png",
"nit": "",
"phone": ""
}
},
"idCompany3": {
"data": {
"address": "",
"companyName": "Company 3",
"logo": "assets/Logo3.png",
"nit": "",
"phone": ""
}
}
},
"users": {
"idUser1": {
"data": "user1#test.com",
"companies": {
"idCompany1": true,
"idCompany3": true
}
},
"idUser2": {
"data": "user2#test.com",
"companies": {
"idCompany2": true
}
}
}
}
Basically what I need to do in the case of user1 is to read the data of the companies to which it belongs, this is Company 1 and Company 3. How can I do that?
The way I found, is by obtaining a list of IDs of those companies, which I have in listaIdEmpresas and then consulting each one through a forEach loop in the following way:
Future<List<EmpresaDatosModel>> cargarEmpresaDatosListado(List<String> listaIdEmpresas) async {
final List<EmpresaDatosModel> listaEmpresas = new List();
listaIdEmpresas.forEach((id) async {
Query resp = db.child('company/$id/data');
final snapshot = await resp.once();
final temp = EmpresaDatosModel.fromJson(Map<String,dynamic>.from(snapshot.value));
temp.idEmpresa = id;
listaEmpresas.add(temp);
print('${temp.companyName} up');
await resp.once().then((snapshot) {});
});
listaEmpresas.forEach((element) {print('Emp ${element.companyName}');});
return listaEmpresas;
}
However, this process is not efficient and I need to manage a delay for waiting the loop.
What would be the right way to do query data from a list of Ids directly?

Iterate through map values in dart / flutter

I am basically from JS background and now trying my hands on flutter framework.
I am stuck in formatting my data I received from API.
Data Received an array of objects
[
{
"id": 1,
"name": "name1",
"type": "Both",
"count": 4
},
{
"id": 2,
"name": "name2",
"type": "Both",
"count": 6
},
{
"id": 3,
"name": "name1",
"type": "Both",
"count": 2
},
{
"id": 4,
"name": "name3",
"type": "Both",
"count": 8
},
......
]
My Requirement is I will have to group the data based on the name
{
name1: [
{
"id": 1, "name":"name1", "type": "Both", "count": 4
},
{
"id": 3, "name":"name1", "type": "Both", "count": 2
}
],
name2: [
{
"id": 2, "name":"name2", "type": "Both", "count": 6
}
],
.....
}
In dart, I have managed to do that grouping using groupBy from collections.dart package.
The problem is I cannot loop through the grouped data. I need to access the count for some manipulation for each grouped name.
Below is the code snipped which I tried
Map data;
List partySnapData;
Map newMap;
Future _getTopParties() async {
final response =await http.get(API_URL + '/getPartySnapShot');
data =json.decode(response.body);
partySnapData = data['resultObj'];
setState(() {
newMap = groupBy(partySnapData, (obj) => obj['party_name']);
for(var v in newMap.values) {
print(v);
}
});
}
The print(v) actually gave me the value mapped for the map E.G
[
{ "id": 1, "name":"name1", "type": "Both", "count": 4 },
{ "id": 3, "name":"name1", "type": "Both", "count": 2 }
],
.....,
......
Now, how do I loop or iterate through the array, here the v, so that i can access the elements inside?
I found a solution to this. I am posting that, incase it helps someone.
I wanted to loop through the v to generate objects.
newMap = groupBy(partySnapData, (obj) => obj['party_name']);
for(var v in newMap.values) {
print(v);
//below is the solution
v.asMap().forEach((i, value) {
print('index=$i, value=$value');
}
}
Ignoring your specific case but answering the question in case others come across this question like I did while searching for How to iterate through map values in dart / flutter.
There is a simpler and a better approach.
Here's the best approach (because this way you can break the for loop after finding the right entry and doing what you had to do to avoid unnecessary iterations).
for (MapEntry<type, type> item in myMap.entries) {
//Here each item has a key and a value proterties.
//Don't forget to use break; to end the loop when you are done and avoid unnecessary iterations.
}
And here is the easier:
myMap.forEach((key, value) {
//Here you have key and value for each item in your map but you can't break the loop
//to avoid unnecessary iterations.
//This approach is only useful when you need to perform changes in all Map items.
});
UPDATED
List<Map> list = [
{
"id": 1,
"name": "name1",
"type": "Both",
"count": 4
},
{
"id": 2,
"name": "name2",
"type": "Both",
"count": 6
},
{
"id": 3,
"name": "name1",
"type": "Both",
"count": 2
},
{
"id": 4,
"name": "name3",
"type": "Both",
"count": 8
}];
Map sorted={};
#override
void initState(){
super.initState();
for(Map m in list){
if(sorted[m['name'].toString()]==null)
sorted[m['name'].toString()]=[];
sorted[m['name'].toString()].add(m);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Container(
padding:EdgeInsets.all(20),
color:Colors.white,
alignment:Alignment.center,
child:Column(
mainAxisSize:MainAxisSize.min,
children: <Widget>[
Text('Original\n $list',
style:TextStyle(color:Colors.black)),
SizedBox(height:15),
Text('Sorted\n $sorted',
style:TextStyle(color:Colors.black)),
//EDIT
SizedBox(height:15),
ListView(
shrinkWrap:true,
children: sorted.entries.map<Widget>((value){
return Column(
mainAxisSize:MainAxisSize.min,
crossAxisAlignment:CrossAxisAlignment.start,
children:[
Text(value.key.toString(),style:TextStyle(color:Colors.black,
fontWeight:FontWeight.bold)),
Column(
mainAxisSize:MainAxisSize.min,
children:value.value.map<Widget>((subValue){
return Text(subValue['count'].toString(),style:TextStyle(color:Colors.black));
}).toList(),
),
]
);
}).toList(),
)
],
)
)
);
}

Flutter return array from response from server

in this part of my code await webApi.getKeywords(); return array which that can get from server, now when i try to return that i get error:
type 'List<dynamic>' is not a subtype of type 'String'
get data from server code:
Future<List<KeywordsResponse>> _getKeywords(BuildContext context) async {
try {
final webApi = Provider.of<WebApi>(context);
final response = await webApi.getKeywords();
List<KeywordsResponse> list = List();
if (response.statusCode == 200) {
list = (json.decode(response.body) as List)
.map((data) => new KeywordsResponse.fromJson(data))
.toList();
return list;
} else {
throw Exception('Failed to load photos');
}
} catch (error) {
print(error);
return null;
}
}
KeywordsResponse class:
#JsonSerializable(nullable: true)
class KeywordsResponse{
#JsonKey(name:'id')
final int id;
#JsonKey(name:'title')
final String title;
#JsonKey(name:'description')
final String description;
KeywordsResponse(this.id, this.title, this.description);
factory KeywordsResponse.fromJson(Map<String, dynamic> json) => _$KeywordsResponseFromJson(json);
Map<String, dynamic> toJson() => _$KeywordsResponseToJson(this);
}
return of response.body:
[
{
"id": 1,
"user_id": 1,
"title": "asdasdasd",
"description": "asdasdasd",
"type": "post",
"slug": "asdasdad",
"featured_images": {
"images": {
"300": "/uploads/post_images/2019/300_1573573784.png",
"600": "/uploads/post_images/2019/600_1573573784.png",
"900": "/uploads/post_images/2019/900_1573573784.png",
"original": "/uploads/post_images/2019/1573573784.png"
},
"thumbnail": "/uploads/post_images/2019/300_1573573784.png"
},
"lang": "fa",
"visit": 0,
"categories": [
{
"id": 1,
"title": "aaaaaaa",
"lang": "fa",
"parent": 0,
"pivot": {
"contents_id": 1,
"content_categories_id": 1
}
}
]
},
{
"id": 2,
"user_id": 1,
"title": "asdasdasd",
"description": "asdadasd",
"type": "post",
"slug": "asdasdasda",
"featured_images": {
"images": {
"300": "/uploads/post_images/2019/300_1573573846.png",
"600": "/uploads/post_images/2019/600_1573573846.png",
"900": "/uploads/post_images/2019/900_1573573846.png",
"original": "/uploads/post_images/2019/1573573846.png"
},
"thumbnail": "/uploads/post_images/2019/300_1573573846.png"
},
"lang": "fa",
"visit": 0,
"categories": [
{
"id": 2,
"title": "bbbbbbbb",
"lang": "fa",
"parent": 0,
"pivot": {
"contents_id": 2,
"content_categories_id": 2
}
}
]
}
]
problem is on this line of code:
json.decode(response.body)
Try this:
list = List<KeywordsResponse>.from(response.body.map((x) => KeywordsResponse.fromJson(x)));