what is the easiest way to merge 2 list of object in flutter dart? - list

what is the easiest way to merge 2 list of object in flutter dart and achieve the result?
List 1
[
{name: eat, frequency: Daily},
{name: read, frequency: Daily},
{name: walk, frequency: Daily,}
]
List 2
[
{name: eat, count: 2},
{name: read, count: 2},
{name: walk, count: 2,}
]
Result
[
{name: eat, count: 2, frequency: Daily},
{name: read, count: 2, frequency: Daily},
{name: walk, count: 2, frequency: Daily}
]

Assuming the lists have the same length and contain Maps:
void main() {
var l1 = [
{'name': 'eat', 'frequency': 'Daily'},
{'name': 'read', 'frequency': 'Daily'},
{'name': 'walk', 'frequency': 'Daily'}
];
var l2 = [
{'name': 'eat', 'count': 2},
{'name': 'read', 'count': 2},
{'name': 'walk', 'count': 2}
];
var l3 = [
for (var i = 0; i < l1.length; i++) {...l1[i], ...l2[i]},
];
print(l3);
// [{name: eat, frequency: Daily, count: 2}, {name: read, frequency: Daily, count: 2}, {name: walk, frequency: Daily, count: 2}]
}

There are several simple ways to combine these lists, but they run into several issues. For example, can you guarantee that the lists will be the same length and that the order of the lists will be identical (as far as the "name" field in the nested maps are concerned)?
If you can't guarantee equal length and matching order, then you need to resort to a slightly more complex approach that is agnostic to either of those issues.
void main() {
final list1 = [
{'name': 'eat', 'frequency': 'Daily'},
{'name': 'read', 'frequency': 'Weekly'},
{'name': 'walk', 'frequency': 'Monthly'},
];
final list2 = [
{'name': 'walk', 'count': 4},
{'name': 'eat', 'count': 2},
{'name': 'read', 'count': 3},
];
// Convert the second list into a lookup table
final lookup = Map.fromIterable(list2, key: (m) => m['name'], value: (m) => m);
// Generate the combined list, using the first list as a base
final combined = list1.map((m) => { ...m, ...lookup[m['name']] }).toList();
print(combined);
// Prints (formatted)
// [
// {name: eat, count: 2, frequency: Daily},
// {name: read, count: 3, frequency: Weekly}
// {name: walk, count: 4, frequency: Monthly},
// ]
}

Related

Flutter: type 'List<Map<String, Object>>' is not a subtype of type 'List<Map<String, int>>' in type cast

During construction of a a prototype for a quiz app using Flutter and VS Code as the IDE, I got the following error:
type 'List<Map<String, Object>>' is not a subtype of type 'List<Map<String, int>>' in type cast
from my quiz.dart file which is
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import './answer.dart';
import './question.dart';
class Quiz extends StatelessWidget {
final Function? fun;
final int? questionIndex;
final List<Map<String, Object>>? array;
Quiz({required this.fun, required this.questionIndex, required this.array});
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(
(array)![questionIndex!]['questionText'] as String,
),
...((array)![questionIndex!]['answers'] as List<Map<String, int>>)
.map((question) {
return Answer((() => (fun!(question['score'])) as VoidCallback),
(question['text'] as String));
}).toList(),
// ...[Text('hello'), Text('okay')],
],
);
}
}
Following is my main.dart file where one can find my plugin for array in the constructor of Quiz widget class.
import 'package:flutter/material.dart';
import './quiz.dart';
import './result.dart';
// void main() {
// runApp(MyApp());
// }
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final _ques = const [
{
'questionText': 'What\'s your fav. color?',
'answers': [
{'text': 'Black', 'score': 10},
{'text': 'Red', 'score': 5},
{'text': 'Green', 'score': 3},
{'text': 'White', 'score': 1},
]
},
{
'questionText': 'What\'s your fav. animal?',
'answers': [
{'text': 'Cat', 'score': 5},
{'text': 'Dog', 'score': 3},
{'text': 'Snake', 'score': 4},
{'text': 'Bird', 'score': 2}
]
},
{
'questionText': 'Who\'s your fav. instructor?',
'answers': [
{'text': 'Max', 'score': 1},
{'text': 'Max', 'score': 1},
{'text': 'Max', 'score': 1}
]
},
];
var _questionIndex = 0;
var _totalScore = 0;
void _hola(int score) {
_totalScore += score;
setState(() => _questionIndex = _questionIndex + 1);
print(_questionIndex);
if (_questionIndex < _ques.length) {
print('We have more questions!!');
}
}
#override
Widget build(BuildContext context) {
// print('hpllll ${context}');
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Ayoo App Bar stuff'),
backgroundColor: Colors.black,
),
body: _questionIndex < _ques.length
? Quiz(questionIndex: _questionIndex, array: _ques, fun: _hola)
: Result(_totalScore),
),
);
}
}
In fact, I get an error even when I use
final List<Map<String,List<Map<String,int>>>> _ques = const [
{
'questionText': 'What\'s your fav. color?',
'answers': [
{'text': 'Black', 'score': 10},
{'text': 'Red', 'score': 5},
{'text': 'Green', 'score': 3},
{'text': 'White', 'score': 1},
]
},
{
'questionText': 'What\'s your fav. animal?',
'answers': [
{'text': 'Cat', 'score': 5},
{'text': 'Dog', 'score': 3},
{'text': 'Snake', 'score': 4},
{'text': 'Bird', 'score': 2}
]
},
{
'questionText': 'Who\'s your fav. instructor?',
'answers': [
{'text': 'Max', 'score': 1},
{'text': 'Max', 'score': 1},
{'text': 'Max', 'score': 1}
]
},
];
to explicitly define the datatype for _ques list. Following is a screenshot showing the error
Any help in regard to fixing/explaining this error is highly appreciated!
Because of the type :
List<Map<String,List<Map<String,int>>>>
You created a list of map where the left Side are always String and the Right side must be always List of Map<String, int>.
I suggest to use the following type instead :
List<Map<String, dynamic>>

type 'List<dynamic>' is not a subtype of type 'Map<dynamic, dynamic>' need to conver list of map as map

the result I got as List
[{name: john, voted: [{5fhh54522b5: 8}, {2cg128gsc4541: 822}]}, {name: Donald, voted: [{8br55rj25ns3j: 822}, {jfej4v85552: 1}]}, {name: Abraham, voted: []}, {name: Colly, voted: []}]
need to convert this data as below map as.....Map<dynamic,dynamic>
{name: john, voted: [{5fhh54522b5: 8}, {2cg128gsc4541: 822}]}, {name: Donald, voted: [{8br55rj25ns3j: 822}, {jfej4v85552: 1}]}, {name: Abraham, voted: []}, {name: Colly, voted: []}
From your gist, I modified the code as follows
void main() {
var dataList = jsonString;
Map<dynamic, dynamic> data = Map<dynamic, dynamic>();
dataList.forEach((item) {
if(item["voted"] != null) {
(item["voted"] as List).forEach((voteItem) {
if(voteItem != null) {
(voteItem as Map).forEach((key, val){
data[key] = val;
});
}
});
}
});
print(data);
//this what I need as reult
// {
// 60e6956078fb6f42da: 1,
// 60e6956020d8bf42db: 5,
// 120d8bf42dffsww66: 1,
// jd58466daa4dw2: 20,
// gg4c577x6ad8ds6a: 6
// }
}
const jsonString = [
{
"voted": [
{
"60e6956078fb6f42da": "1"
},
{
"60e6956020d8bf42db": "5"
}
],
"_id": "60e698fe78fb6120d8bf42dd",
"name": "donald"
},
{
"voted": [
{
"120d8bf42dffsww66": "1"
}
],
"_id": "60e698fe78fb6120d8bf42de",
"name": "barrack"
},
{
"voted": [
{
"jd58466daa4dw2": "20"
}
],
"_id": "60e698fe78fb6120d8bf42df",
"name": "malan"
},
{
"voted": [
{
"gg4c577x6ad8ds6a": "6"
}
],
"_id": "60e698fe78fb6120d8bf42e0",
"name": "kuma"
}
];
i don't think this is map
{name: john, voted: [{5fhh54522b5: 8}, {2cg128gsc4541: 822}]}, {name: Donald, voted: [{8br55rj25ns3j: 822}, {jfej4v85552: 1}]}, {name: Abraham, voted: []}, {name: Colly, voted: []}
they are multiple maps, not single map.
you can use list.asMap() function to convert list of any to map,
HI, i tried in dart pad, i can see that it is not valid json,
you have to convert it like this, after that it you will be able to parse the json string easily
voted :[ { id : '5fhh54522b5', count : '8'}, ]

Merging a list of dictionaries

I have a list of dicts as below.
list = [ {id: 1, s_id:2, class: 'a', teacher: 'b'} ]
list1 = [ {id: 1, c_id:1, rank:2, area: 34}, {id:1, c_id:2, rank:1, area: 21} ]
I want to merge the two lists on the common key-value pairs (in this case 'id:1')
Merged_list = [ {id:1, s_id:2, class: 'a', teacher: 'b', list1: {c_id:1, rank: 2, area: 34}, {c_id:2, rank: 1, area: 21} ]
How do I go about this?
Thanks
You can use
merged_list = [{**d1, **d2} for d1, d2 in zip(list1, list2)]
>>> merged_list
[{'id': 1, 's_id': 2, 'class': 'a', 'teacher': 'b', 'rank': 2, 'area': 34},
{'id': 2, 's_id': 3, 'class': 'c', 'teacher': 'd', 'rank': 1, 'area': 21}]
where {**d1, **d2} is just a neat way to combine 2 dictionaries. Keep in mind this will replace the duplicate keys of the first dictionary. If you're on Python 3.9, you could use d1 | d2.
EDIT: For the edit in your question, you can try this horrible one liner (keep in mind this will create the pair list1: [] if no matching indeces were found on list1):
list_ = [{"id": 1, "s_id": 2, "class": 'a', "teacher": 'b'}]
list1 = [{"id": 1, "c_id": 1, "rank": 2, "area": 34}, {"id": 1, "c_id": 2, "rank": 1, "area": 21}]
merged_list = [{**d, **{"list1": [{k: v for k, v in d1.items() if k != "id"} for d1 in list1 if d1["id"] == d["id"]]}} for d in list_]
>>> merged_list
[{'id': 1,
's_id': 2,
'class': 'a',
'teacher': 'b',
'list1': [{'c_id': 1, 'rank': 2, 'area': 34},
{'c_id': 2, 'rank': 1, 'area': 21}]}]
This is equivalent to (with some added benefits):
merged_list = []
for d in list_:
matched_ids = []
for d1 in list1:
if d["id"] == d1["id"]:
d1.pop("id") # remove id from dictionary before appending
matched_ids.append(d1)
if matched_ids: # added benefit of not showing the 'list1' key if matched_ids is empty
found = {"list1": matched_ids}
else:
found = {}
merged_list.append({**d, **found})
Try this
And don't forget to put " " when declare string
list = [ {"id": 1, "s_id": 2 ," class": 'a', "teacher": 'b'}, {"id": 2, "s_id" : 3, "class" : 'c', "teacher": 'd'} ]
list1 = [ {"id": 1, "rank" :2, "area" : 34}, {"id" :2, "rank" :1, "area": 21} ]
list2 = list1 + list
print(list2)

How to generate a reliable `hasMoreResults` value for pagination in DynamoDB queries

I am trying to perform pagination on a simple DynamoDB table for queries by date range, and had hoped to coerce the LastEvaluatedKey into a "hasMoreResults" boolean value for my front end to consume, but now see that a non-empty LastEvaluatedKey can sometimes appear on results even when the number of items within the date range does not exceed my LIMIT. Does this mean that I will always need to perform a subsequent query that will return no additional items?
My table looks something like:
[
{PK: "john", SK: "2021-01-01:08:00", amount: 1},
{PK: "john", SK: "2021-01-01:20:00", amount: 2},
{PK: "john", SK: "2021-01-02:08:00", amount: 3},
{PK: "john", SK: "2021-01-02:20:00", amount: 4},
{PK: "john", SK: "2021-01-03:08:00", amount: 5},
{PK: "john", SK: "2021-01-03:20:00", amount: 6}
...and on for all of January
];
Using the JavaScript DocumentClient, my query looks like:
async function getEntriesByDate({name, startDate, endDate, limit, sort}) {
return await docClient.query({
TableName: "someTableName",
KeyConditionExpression: "#pk = :pk and #sk Between :startDate And :endDate",
ExpressionAttributeNames: {
"#pk": "PK",
"#sk": "SK"
},
ExpressionAttributeValues: {
":pk": name,
":startDate": startDate,
":endDate": endDate
},
ScanIndexForward: sort === "asc",
Limit: limit
}).promise();
}
If I call the function with the end date exactly matching the date of the fourth item and a LIMIT of 4:
getEntriesByDate({name: "john", startDate: "2021-01-01:08:01", endDate: "2021-01-02:20:01", limit: 4, sort:"asc"});
I get the following result:
{
"Items": [
{"PK": "john", "SK": "2021-01-01:08:00", "amount": 1},
{"PK": "john", "SK": "2021-01-01:20:00", "amount": 2},
{"PK": "john", "SK": "2021-01-02:08:00", "amount": 3},
{"PK": "john", "SK": "2021-01-02:20:00", "amount": 4 }
],
"Count": 4,
"ScannedCount": 4
}
Great, there's no LastEvaluatedKey. which is what I expect. But if I call the function with the same args except adding a minute to the end date, I get:
{
"Items": <same as in last query, which is expected>,
"Count": 4,
"ScannedCount": 4,
"LastEvaluatedKey": {
"SK": "2021-01-02:20:00",
"PK": "john"
}
}
and LastEvaluatedKey does appear, even though there are no additional items that satisfy the query. Is there an idiomatic solution to this problem? Is a subsequent query, perhaps using ExclusiveStartKey, necessary inside my function in order to secure a reliable hasMoreResults value?

how to count number of occurrences of element in list of maps in dart?

I have a list of maps like this
data = [
{
'id': 100,
'quantity': 20
},
{
'id': 101,
'quantity': 25
},
{
'id': 101,
'quantity': 30
}
{
'id': 105,
'quantity': 50
}
]
I am able to count occurrences of element in a list like this
data.forEach((x) => map[x] = !map.containsValue(x) ? (1) : (map[x] + 1));
print(map);
Output :
{{id: 100, quantity: 20}: 1, {id: 101, quantity: 25}: 1, {id: 101, quantity: 30}: 1, {id: 105, quantity: 50}: 1}
But I want to count how many times id = 101 comes in the list so How can I achieve that?
You can use where to filter your array of maps and then use the getter length :
var data = [
{'id': 100, 'quantity': 20},
{'id': 101, 'quantity': 25},
{'id': 101, 'quantity': 30},
{'id': 105, 'quantity': 50}
];
print(data.where((e) => e['id'] == 101).length); // 2