Add/Update list of K,V pair to empty declared map = List<Map<dynamic, dynamic>> - flutter

I have and empty map, Map optionSelection = {};
And on every button click I want to add list of K,V pair map to optionSelection map.
Format in which I want to add Map.
{
"quiz_id": selectedOption,
"ques_id": questionId,
"user_ans_id": selectedOption,
}
In above Key and Value pair, in "ques_id": questionId -> questionId will be unique, So I want to check if the value already exist, if YES then I want to update the "user_ans_id": selectedOption value or else I want to add new list of K,V pair.
Below is the code I tried
final quesExist = optionSelection.containsValue(questionId);
if (quesExist) {
optionSelection.putIfAbsent(
"ques_id",
() => optionSelection.addAll(
{
"quiz_id": selectedOption,
"ques_id": questionId,
"user_ans_id": selectedOption,
},
),
);
} else {
optionSelection.addAll(
{
"quiz_id": selectedOption,
"ques_id": questionId,
"user_ans_id": selectedOption,
},
);
}
Hope I was able to explain my issue, Thank you in advance.

after a week of struggle and many tweaks in code, here is the final solution for above query.
// Declared empty List<Map>
List<Map> optionSelection = [];
// Variable to store bool value, if the question id exist
var questionExist;
// Feed the map in below form
Map<String, dynamic> userSelection = {
"quiz_id": widget.quizId,
"ques_id": questionId,
"user_ans_id": selectedOption,
};
// Check if the Ques Id Exist in List<Map> optionSelection
questionExist = optionSelection.any((map) => map.containsValue(questionId));
// Check using if else condition, if Ques Id exist, then run the forLoop,
// to iterate in List<Map>, else add a new Set of Map to the List<Map>
if (questionExist == true) {
print("If triggered");
for (var map in optionSelection) {
if (map.containsValue(questionId)) {
map.update("user_ans_id", (dynamic val) => selectedOption);
}
}
} else {
print("Else triggered");
optionSelection.add(userSelection);
}

Related

how to check if a typing value contains a list of map

I have a list of map, so I want to check If the value I type contains any of the key value before adding.
here is my code:
for (var check in disciplineList) {
if (check.containsKey('degree') ||
!check.containsKey('degree')) {
if (check['degree'] != discipline.text) {
disciplineList.add({
'degree': discipline.text,
'date': currentDate
});
setState1(() {});
setState(() {});
discipline.clear();
currentDate = DateTime.now();
print(disciplineList);
} else {
openCustomDialog(
context: context,
body: '',
heading: 'Item Already Exists!');
print("Item Already Exists!");
}
}
}
In case you have some List of Maps listOfMaps and you want to check if it contains
1- a specific key
you can do so like this:
bool doesItContainKey(var key)
{
return listOfMaps.any((element) => element.keys.contains(key));
}
2- a specific value
you can do so like this:
bool doesItContainValue(var value)
{
return listOfMaps.any((element) => element.values.contains(value));
}
3- a specific map:
you can do so like this:
bool doesItContainMap(var map)
{
return listOfMaps.any((element) => element==map);
}

Fixed List is not updating with for loop - Flutter

I've a fixed list reservedGuest. After checking the condition in for loop I want to update the seats if the membership date has expired. The list is not updating. The code is as follows. PS. The List is filled through API on init().
class MyClubController extends GetxController {
List goldLane = List.filled(3, null, growable: false);
void _alterLanesOnContractEnds() {
for (var i in goldLane) {
print("\n\n I: $i");
if (i == null ||
DateTime.parse(i['contractEnds']).isBefore(
DateTime.now(),
)) {
i = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
}
A for-in loop will not allow you to reassign elements of the List. When you do:
for (var i in goldLane) {
// ...
i = null;
}
you are reassigning what the local i variable refers to, not mutating the goldLane List.
You instead can iterate with an index:
void _alterLanesOnContractEnds() {
for (var i = 0; i < goldLane.length; i += 1) {
var element = goldLane[i];
print("\n\n I: $element");
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
goldLane[i] = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
You can just create a new List where unqualified guests are nullified. For example,
void _alterLanesOnContractEnds() {
goldLane = goldLane.map(
(guest) => guest == null || DateTime.parse(guest['contractEnds']).isBefore(DateTime.now()) ? null: guest
).toList(growable: false);
update();
}
You should not and cannot modify a list while iterating with its iterator.
Elaborated by Jamesdlin,
Modifying the elements of a List while iterating is fine. Modifying
the length of the List while iterating is not, but that won't be a
problem for a non-growable List.
The bottom line is you should not mutate the size of the list while iterating.
I solved it by using
goldLane.forEach(
(element) {
print('\n\n ELEMENT: $element');
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
int ix = goldLane.indexWhere(
(element) => element != null
? DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)
: true,
);
goldLane[ix] = null;
} else {
print('Cannot be removed');
}
},
);
Yet I'll test the other answers. Thank You.

Unable to add key and bool value into nested list

Example Code (Not working):
void main() {
List json = [
{
"sku": "SKU0001",
"uids": [
{
"uid": "U001"
}
]
}
];
var result = json.map( (item) {
item['no_desc'] = true; // able to add the key and bool value
item['uids'] = item['uids'].map( (uid) {
uid['is_scanned'] = true; // failed to add, but able to accept string value only.
return uid;
}).toList();
return item;
}).toList();
print(result);
}
return error 'bool' is not a subtype of type 'String'
Expected Result
[
{
sku: SKU0001,
no_desc: true,
uids: [
{
uid: U001,
is_scanned: true // must be boolean
}
]
}
]
It work when i try in String value.
uid['is_scanned'] = 'true';
How can I add bool value into the nested list?
If I am writing in javascript way,
it should be able to add the key into nested array ( list ).
But why in dart lang, it prompt me error?
Can someone expert in dart lang willing to explain to me?
Your issue can be fixed by creating a new Map instance in the inner .map method with the Map.from constructor.
item['uids'] = item['uids'].map( (uid) {
uid['is_scanned'] = true; // failed to add, but able to accept string value only.
return uid;
}).toList();
should be changed to:
item['uids'] = item['uids'].map( (uid) {
Map<String, dynamic> toReturn = Map.from(uid);
toReturn['is_scanned'] = true;
return toReturn;
}).toList();
I believe this issue is due to dart implicitly declaring the inner uids maps as Map<String, String> so creating a new instance changes this and allows you to assign any value to the keys of the Map.
Full working sample:
void main() {
List json = [
{
"sku": "SKU0001",
"uids": [
{
"uid": "U001"
}
]
}
];
var result = json.map( (item) {
item['no_desc'] = true;
item['uids'] = item['uids'].map( (uid) {
Map<String, dynamic> toReturn = Map.from(uid);
toReturn['is_scanned'] = true;
return toReturn;
}).toList();
return item;
}).toList();
print(result);
}

delete duplicates from a list in dart

hey there i am trying to display all of the options from my database in a dropdown,i have them displaying but i only want one of each result to appear and i cant figure out how to to get ride of the duplicates this is what it looks like when i click on the dropdown
here is the code to pull in the results
void _getFieldsData() {
getUserDetails().then((data) {
final items = jsonDecode(data).cast<Map<String, dynamic>>();
var fieldListData = items.map<User>((json) {
return User.fromJson(json);
}).toSet().toList();
///set list for class
_selectedField = fieldListData[0].series;
_selectedField = fieldListData[0].classs;
setState(() {
for (Map user in items) {
_userDetails.add(User.fromJson(user));
print(_userDetails.length);
//if (_userDetails.classs != userDetail.classs.contains(_selectedText))
}
});
// update widget
setState(() {
_fieldList = fieldListData.toSet().toList();
//print(resultseries);
// print(uniqueCount);
print(_fieldList);
});
});
here is the dropdown
new DropdownButton<String>(
hint: Text("Series"),
// value: null,
items: _fieldList.map((value){
return DropdownMenuItem<String>(
value: value.series,
child: Container(
width: 100,
child: new Text(value.series),
it's not clear exactly what your User class looks like, but im assuming you have multiple fields that do not all have same values, for example, each with a unique id, that's why the following line isn't working in your case:
setState(() {
_fieldList = fieldListData.toSet().toList();
});
i would suggest using List.fold, List.any, and change the line above to check for only .series field, as below:
List initialResultsList = [];
setState(() {
// use fold (similar to .reduce()) to iterate through fieldListData and return the updated filtered 'results'
// list with each iteration:
_fieldList = fieldListData.fold(initialResultsList, (results, currentItem) {
// check to see if currentItem.series already exists in any item of filtered results:
if (!results.any((item) => item.series == currentItem.series)) {
// if not, add it to results:
results.add(currentItem);
}
// return results for next iteration
return results;
});
}

Check whether a list contain an attribute of an object in dart

I need to check whether myItemsList contains myitem.itemId or not, If it exists need to add itemQuantity, if it not exists need to add myitem object to myItemsList.
List<MyItem> myItemsList = new List();
MyItem myitem = new MyItem (
itemId: id,
itemName: name,
itemQuantity: qty,
);
if (myItemsList.contains(myitem.itemId)) {
print('Already exists!');
} else {
print('Added!');
setState(() {
myItemsList.add(myitem);
});
}
MyItem class
class MyItem {
final String itemId;
final String itemName;
int itemQuantity;
MyItem ({
this.itemId,
this.itemName,
this.itemQuantity,
});
}
above code is not working as expected, please help me to figure out the issue.
Contains() compares the whole objects.
Besides overriding == operator or looping over, you can use list's singleWhere method:
if ((myItemsList.singleWhere((it) => it.itemId == myitem.itemId,
orElse: () => null)) != null) {
Edit:
As Dharaneshvar experienced and YoApps mentioned in the comments .singleWhere raises StateError when more elements are found.
This is desired when you expect unique elements such as in the case of comparing IDs.
Raised error is the friend here as it shows that there is something wrong with the data.
For other cases .firstWhere() is the right tool:
if ((myItemsList.firstWhere((it) => it.itemName == myitem.itemName,
orElse: () => null)) != null) {
// EO Edit
Whole example:
List<MyItem> myItemsList = new List();
​
class MyItem {
final String itemId;
final String itemName;
int itemQuantity;
​
MyItem({
this.itemId,
this.itemName,
this.itemQuantity,
});
}
​
void main() {
MyItem myitem = new MyItem(
itemId: "id00",
itemName: "name",
itemQuantity: 50,
);
​
myItemsList.add(myitem);
​
String idToCheck = "id00";
​
if ((myItemsList.singleWhere((it) => it.itemId == idToCheck,
orElse: () => null)) != null) {
print('Already exists!');
} else {
print('Added!');
}
}
As already said before, contains compares two Objects with the == operator. So you currently compare MyItem with String itemId, which will never be the same.
To check whether myItemsList contains myitem.itemId you can use one of the following:
myItemsList.map((item) => item.itemId).contains(myitem.itemId);
or
myItemsList.any((item) => item.itemId == myitem.itemId);
You're using contains slightly wrong.
From: https://api.dartlang.org/stable/2.2.0/dart-core/Iterable/contains.html
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}
You can either override the == operator, see: https://dart-lang.github.io/linter/lints/hash_and_equals.html
#override
bool operator ==(Object other) => other is Better && other.value == value;
Or you can loop over your list and search the normal way one by one, which seems slightly easier.
One more way to check does list contain object with property or not
if (myList.firstWhereOrNull((val) => val.id == someItem.id) != null) {}