How to transform List into Map of List - flutter

I have a list with this data and I want to transform this in a Map<DateTime, List> with as variable for event (_id, title, date, active), ere is an example of data that I recover:
[
{
"_id":8,
"title":"Matin",
"date":"2021-08-04T00:00:00.000Z",
"active":1
},
{
"_id":9,
"title":"Après-midi",
"date":"2021-08-04T12:00:00.000Z",
"active":1
},
{
"_id":11,
"title":"Matin",
"date":"2021-08-05T00:00:00.000Z",
"active":1
},
{
"_id":12,
"title":"Après-midi",
"date":"2021-08-05T12:00:00.000Z",
"active":1
},
{
"_id":6,
"title":"Matin",
"date":"2021-08-11T00:00:00.000Z",
"active":1
},
{
"_id":7,
"title":"Après-midi",
"date":"2021-08-11T12:00:00.000Z",
"active":1
},
{
"_id":4,
"title":"Matin",
"date":"2021-08-17T00:00:00.000Z",
"active":1
},
{
"_id":10,
"title":"Matin",
"date":"2021-08-17T00:00:00.000Z",
"active":1
}
]
And in each value I have a date with year, month, day and time and I would like to group the dates without taking the hour into account, what will look like this:
"2021-08-04": [
{
"_id":8,
"title":"Matin",
"date":"2021-08-04T00:00:00.000Z",
"active":1
},
{
"_id":9,
"title":"Après-midi",
"date":"2021-08-04T12:00:00.000Z",
"active":1
}
],
"2021-08-05": [
[
{
"_id":11,
"title":"Matin",
"date":"2021-08-05T00:00:00.000Z",
"active":1
},
{
"_id":12,
"title":"Après-midi",
"date":"2021-08-05T12:00:00.000Z",
"active":1
}
]
I try to do something with Map.fromIterable but I have some error...
If someone can help me thanks !

I brute-forced the solution type you need. The provided solution will work for sure if the format of the date stored doesn't change.
void converter(var data) {
var req={};
for (int i = 0; i < data.length; i++) {
var date=data[i]["date"].toString().substring(0,10);
if(!req.containsKey(date))
req[date]=[];
req[date].add(data[i]);
}
print(req);
}

As you are using flutter there is a package that can handle this of stuff.
https://pub.dev/packages/collection
you will need groupby.
i did something like that, idk if the api is still the same. Anyhow here is the snippet.
.map(
(List<Appointment> appointments) {
appointments.sort(
(Appointment a, Appointment b) {
if (a.appointmentdate
.difference(b.appointmentdate)
.isNegative) return -1;
return 1;
},
);
return appointments;
},
).distinct();

Considering that data is the List<Map<String, Object>> variable you listed, i.e. assuming your data is not a JSON object, I'd do:
Map<String, List<Map<String,Object>>> myTfData = {}
data.forEach(
(value) {
var myDate = value['date'] as String;
if(myTfData.containsKey(myDate)) myTfData[myDate] = [];
myTfData[myDate]!.add(value);
}
);
You'd obtain a Map<String, List<Map<String,Object>>> object as requested.

Related

How to remove duplicate item from list of maps with it's property in Flutter | Dart

I have a list of Maps. The below is the list of maps,
List teachers = [
{
'name':'John',
'subject':'English'
},
{
'name':'Rohan',
'subject':'Hindi'
},
{
'name':'Benny',
'subject':'English'
},
{
'name':'Rose',
'subject':'Tamil'
},
{
'name':'Shine',
'subject':'Kannada'
},
{
'name':'Tintu',
'subject':'English'
}
];
From this I want to keep any of the one english teacher and remove all other teacher with subject english.
The below is the expected result.
List teachers = [
{
'name':'John',
'subject':'English'
},
{
'name':'Rohan',
'subject':'Hindi'
},
{
'name':'Rose',
'subject':'Tamil'
},
{
'name':'Shine',
'subject':'Kannada'
},
];
You can use collection package and try this:
var grouped =
groupBy(teachers, (Map<String, String> value) => value['subject']);
List<Map> result = grouped.entries.map((e) => e.value.first).toList();
print("result =$result");//result =[{name: John, subject: English}, {name: Rohan, subject: Hindi}, {name: Rose, subject: Tamil}, {name: Shine, subject: Kannada}]

Group by and Get Max Value MongoDb

I would like to get the highest number of counts for each numId and display it on my front end in a table.
Here is an example of my database:
{
"_id": {
"$oid": "6294777f677b4c647e28771a"
},
"numId": "5",
"respondee": "0x9d95bcaa5b609fa97a7ec860bec115aa94f85ba9",
"__v": 0,
"originalResponse": "test2",
"submittedAt": {
"$date": {
"$numberLong": "1653897087357"
}
},
"addresses": [
"0x39c878a3df98002ddba477a7aa0609fb5a27e2ff",
"0xe3342d6522ad72f65d6b23f19b17e3fb12161f90"
],
"count": 2
},
{
"_id": {
"$oid": "6294836e677b4c647e287e93"
},
"numId": "5",
"respondee": "0xe3342d6522ad72f65d6b23f19b17e3fb12161f90",
"__v": 0,
"originalResponse": "test3",
"submittedAt": {
"$date": {
"$numberLong": "1653900142375"
}
},
"addresses": [
],
"count": 0
}
I have written something like this but I'm not sure how to group the results according to the numId
import Response from '../../../models/Response.model';
import db from '../../../utils/config/db';
import nc from 'next-connect';
import { onError } from '../../../utils/error';
const handler = nc({
onError,
});
//GET all
handler.get(async (req, res) => {
await db.connect();
let responses = await Response.find({ });
//To group responses by numId
// Sort responses by votes in ascending order
responses = responses.sort((a, b) => {
return a.count - b.count;
});
let topResponses = responses.filter((response) => {
return response.count === responses[0].count;
});
// Check if respondee has the highest count response
if (
topResponses.length > 0 &&
topResponses.find((response) => {
return response.respondee === respondee;
})
) {
// Get the response
let response = topResponses.find((response) => {
return response.respondee === respondee;
});
// Get the response
let responseString = response.response;
// Get the count
let count = response.count;
}
await db.disconnect();
});
export default handler;
I have figured out the answer by referring from another stackoverflow:
Group by and Get Max Value MongoDb
let responses = await Response.aggregate([
{ $sort: { votes: -1 } },
{ $group: { _id: '$baseId', group: { $first: '$$ROOT' } } },
{ $replaceRoot: { newRoot: '$group' } },
]);
res.send(responses);

Flutter/Dart group list by date

I have following list of maps,
[
{
"FullName":"Harry Potter",
"DateOfBirth": "2020/02/16",
"Department":"Branch Operation",
"BirthDay":"Friday"
},
{
"FullName":"John Wick",
"DateOfBirth": "2020/02/16",
"Department":"Finance",
"BirthDay":"Friday"
},
{
"FullName":"Solomon Kane",
"DateOfBirth":2020/02/19,
"Department":"Loan",
"BirthDay":"Monday"
}
]
I would like to manipulate above data such that data are grouped by their DateOfBirth, so that result would look like this.
[
{
"DateOfBirth": "2020/02/16",
"BirthDay": "Friday",
"Data":[
{
"FullName": "Harry Potter",
"Department":"Branch Operation",
},
{
"FullName":"John Wick",
"Department":"Finance",
}
]
},
{
"DateOfBirth": "2020/02/19",
"BirthDay": "Monday",
"Data":[
{
"FullName":"Solomon Kane",
"Department":"Loan"
}
]
},
]
In Javascript, this can be achieved by using reduce function and then using Object key mapping.
I also know dart has useful package called collection
As I am new to dart and flutter, I am not sure how to do. Can anybody help me on this?
Thanks
You could use fold and do something like this
const data = [...];
void main() {
final value = data.fold(Map<String, List<dynamic>>(), (Map<String, List<dynamic>> a, b) {
a.putIfAbsent(b['DateOfBirth'], () => []).add(b);
return a;
}).values
.where((l) => l.isNotEmpty)
.map((l) => {
'DateOfBirth': l.first['DateOfBirth'],
'BirthDay': l.first['BirthDay'],
'Data': l.map((e) => {
'Department': e['Department'],
'FullName': e['FullName'],
}).toList()
}).toList();
}
Or like this if you want to use the spread operator, I don't know if its very readable though.
final result = data.fold({}, (a, b) => {
...a,
b['DateOfBirth']: [b, ...?a[b['DateOfBirth']]],
}).values
.where((l) => l.isNotEmpty)
.map((l) => {
'DateOfBirth': l.first['DateOfBirth'],
'BirthDay': l.first['BirthDay'],
'Data': l.map((e) => {
'Department': e['Department'],
'FullName': e['FullName'],
}).toList()
}).toList();

Difficulty in parsing JSON

I want to develop a flutter app and I am finding it difficult to parse this JSON I have seen posts regarding this but I am finding it difficult to parse this. Help a beginner out! Here is the JSON link " https://api.covid19india.org/state_district_wise.json "
I am simply using:
Future getJsonDistrictData() async {
var response = await http.get(Uri.encodeFull(url1));
var converttojson1 = json.decode(response.body);
setState(() {
myData= converttojson1;
});
}
Text("${myData['Kerala']['districtData']['Thrissur']['confirmed']}")
But this would mean I have to write the same line for every district confirmed cases.
How should I proceed?
I have made the following example of an implementation you can use the parse the data from the URL in your question.
It can be simplified if you don't need the lastUpdatedTime and delta_confirmed since it looks like this is always the empty String and zero in the API.
import 'dart:convert';
class State {
final Map<String, DistrictData> districts = {};
State.fromJson(dynamic json) {
for (final district in json['districtData'].keys) {
districts[district as String] =
DistrictData.fromJson(json['districtData'][district]);
}
}
#override
String toString() => districts.toString();
}
class DistrictData {
final int confirmed;
final DateTime lastUpdatedTime;
final int delta_confirmed;
DistrictData(this.confirmed, this.lastUpdatedTime, this.delta_confirmed);
factory DistrictData.fromJson(dynamic json) => DistrictData(
json['confirmed'] as int,
(json['lastupdatedtime'].isEmpty as bool)
? null
: (DateTime.parse(json['lastupdatedtime'] as String)),
json['delta']['confirmed'] as int);
#override
String toString() =>
'{ confirmed: $confirmed, lastUpdatedTime: $lastUpdatedTime, delta_confirmed: $delta_confirmed }';
}
void main() {
final states = json.decode(input).map(
(String key, dynamic value) => MapEntry(key, State.fromJson(value)))
as Map<String, State>;
states.forEach((key, value) => print('$key : $value'));
/*
Kerala : {Thrissur: { confirmed: 13, lastUpdatedTime: null, delta_confirmed: 0 }, Alappuzha: { confirmed: 5, lastUpdatedTime: null, delta_confirmed: 0 }}
Delhi : {East Delhi: { confirmed: 1, lastUpdatedTime: null, delta_confirmed: 0 }}
*/
}
const input = '''
{
"Kerala": {
"districtData": {
"Thrissur": {
"confirmed": 13,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
},
"Alappuzha": {
"confirmed": 5,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
}
}
},
"Delhi": {
"districtData": {
"East Delhi": {
"confirmed": 1,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
}
}
}
}
''';
Copy your JSON in this link(https://javiercbk.github.io/json_to_dart/) and get model Class.
Example:
For example your Model Class Name is CovidModel. As you get response from network call, pass data to you model class and get object like this:
CovidModel _covidModel = CovidModel.fromJson(response.data);
now you can use _covidModel to get inner objects and show result in app page.

sum value and remove duplicates in List

I have this list and want to sum value and remove duplicates in List
1 - check of productName
2 - sum NumberOfItems if productName equals
For Example :
"Orders":[
{
"productName":"Apple",
"NumberOfItems":"5"
},
{
"productName":"Orange",
"NumberOfItems":"2"
},
{
"productName":"Egg",
"NumberOfItems":"5"
},
{
"productName":"Apple",
"NumberOfItems":"3"
},
{
"productName":"Orange",
"NumberOfItems":"4"
},
{
"productName":"Egg",
"NumberOfItems":"9"
},
]
The result I need look like this result : (Sum Depend on productName)
"Orders":[
{
"productName":"Apple",
"NumberOfItems":"8"
},
{
"productName":"Orange",
"NumberOfItems":"6"
},
{
"productName":"Egg",
"NumberOfItems":"14"
},
]
final orders = data["Orders"] as List;
final mapped = orders.fold<Map<String, Map<String, dynamic>>>({}, (p, v) {
final name = v["productName"];
if (p.containsKey(name)) {
p[name]["NumberOfItems"] += int.parse(v["NumberOfItems"]);
} else {
p[name] = {
...v,
"NumberOfItems": int.parse(v["NumberOfItems"])
};
}
return p;
});
final newData = {
...data,
"Orders": mapped.values,
};
print(newData);
Result is:
{Orders: ({productName: Apple, NumberOfItems: 8}, {productName: Orange, NumberOfItems: 6}, {productName: Egg, NumberOfItems: 14})}
Notice: This code has 2 loop which means slower.
Igor Kharakhordin answered smarter one, but may be difficult for those who ask this question.(since he is doing two things at once.) Basically I am doing same thing.
String string = await rootBundle.loadString("asset/data/Orders.json");
Map orders = jsonDecode(string);
List orderList = orders["Orders"];
Map<String,int> sums = {};
for(int i = 0 ; i < orderList.length; i++){
dynamic item = orderList[i];
if(sums.containsKey(item["productName"])){
sums[item["productName"]] += int.parse(item["NumberOfItems"]);
}
else{
sums[item["productName"]] = int.parse(item["NumberOfItems"]);
}
}
List sumList = [];
sums.forEach((key,value)=>
sumList.add({
"productName":key,
"NumberOfItems":value.toString()
})
);
Map result = {
"Orders":sumList
};
print(jsonEncode(result));
Result
{
"Orders": [
{
"productName": "Apple",
"NumberOfItems": "8"
},
{
"productName": "Orange",
"NumberOfItems": "6"
},
{
"productName": "Egg",
"NumberOfItems": "14"
}
]
}