Dart Map increment the value of a key - flutter

I'm currently working with a Map in which the values are of type integer but I need to update the value of a key every time an action takes place. Example: if the Map is { "key1": 1 } after the actions takes place it should be {"key1":2} and so on. Here's my code:
void addToMap(Product product) {
if (_order.containsKey(product.name)) {
_order.update(product.name, (int) => _order[product.name]+1);
}
_order[product.name] = 1;
}
Where _order is the Map

You may use the following idiomatic approach in Dart:
map.update(
key,
(value) => ++value,
ifAbsent: () => 1,
);
This uses the built-in update method along with the optional ifAbsent parameter that helps set the initial value to 1 when the key is absent in the map. It not only makes the intent clear but also avoids pitfalls like that of forgetting to place the return statement that had been pointed out in the other answer.
Additionally, you may also wrap up the above method as an Extension to Map<dynamic, int>. This way also makes the call site look much less cluttered, as visible from the following demo:
extension CustomUpdation on Map<dynamic, int> {
int increment(dynamic key) {
return update(key, (value) => ++value, ifAbsent: () => 1);
}
}
void main() {
final map = <String, int>{};
map.increment("foo");
map.increment("bar");
map.increment("foo");
print(map); // {foo: 2, bar: 1}
}

Add return or the map will always get overridden by _order[product.name] = 1;
void addToMap(Product product) {
if (_order.containsKey(product.name)) {
_order.update(product.name, (int) => _order[product.name]+1);
return;
}
_order[product.name] = 1;
}

Related

How to update Map's key with new value if the key exists?

I have a todoDate (Map<String, List> variable), and I add a key but sometimes the key already exists therefore nothing is added to the Map data type I want to add the value to the existing key but doesn't work.I have 2 textfields (each one has a controller) and a button: addKey() functionality in the button's onPressed.
void addKey()
{
for (var key in todoDate.keys) {
final containsKey = todoDate.containsKey(key);
if (containsKey) {
todoDate.update(key, (value) => todoDate[key] = value);
} else {
// if key doesn't exist, create new key and value
setState(() { todoDate[dateController.text.toTitleCase()] = [ taskController.text.toTitleCase() ]; });
}
}
}
However it doesn't work, I think the I wrote the update method wrong so how do I do that correct?
update function already has a parameter called ifAbsent. So what you need is just passing the new value to the update and to the ifAbsent.
your function would look like this:
void addKey(key,newValue) {
todoDate.update(key, (value) => newValue,ifAbsent: () => newValue);
}

How remove element duplicates in a list flutter

I am streaming api. With the API, I get 1 item each and add to the list. The fact is that the api stream works in a circle, and duplicates are added to the list. How can I eliminate duplicates?
Code add list:
groupData.map((dynamic item) => GetOrder.fromJson(item))
.where((element) {
if (element.orderId != null) {
if (!list.contains(element)) {
list.add(element);
}
return true;
} else {
return false;
}
}).toList();
If elements are primitives, you can use a Set:
final myList = ['a', 'b', 'a'];
Set.from(myList).toList(); // == ['a', 'b']
but if elements are objects, a Set wouldn't work because every object is different from the others (unless you implement == and hashCode, but that goes beyond this answer)
class TestClass {
final String id;
TestClass(this.id);
}
...
final myClassList = [TestClass('a'), TestClass('b'), TestClass('a')];
Set.from(myClassList).toList(); // doesn't work! All classes are different
you should filter them, for example creating a map and getting its values:
class TestClass {
final String id;
TestClass(this.id);
}
...
final myClassList = [TestClass('a'), TestClass('b'), TestClass('a')];
final filteredClassList = myClassList
.fold<Map<String, TestClass>>({}, (map, c) {
map.putIfAbsent(c.id, () => c);
return map;
})
.values
.toList();
That said, this should work for you
groupData
.map((dynamic item) => GetOrder.fromJson(item))
.fold<Map<String, GetOrder>>({}, (map, element) {
map.putIfAbsent(element.orderId, () => element);
return map;
})
.values
.toList();
You can use Set instead
A Set is an unordered List without duplicates
If this is not working, then chances are that u have different object for the same actual object. (meaning, you have in 2 different places in memory)
In this case .contains or Set will not work

How can I use firstWhereOrNull with a map in Flutter?

How can I use firstWhereOrNull with maps in Flutter?
In other words, how can I do this:
final myVariable1 = myList.firstWhereOrNull(
(myVariable2) =>
!myList.containsValue(myVariable2));
Instead of using a list (myList), I'd like to do the same with a map (Map<String,int>).
Map<String,int> myMap = {};
myMap("stuff1") = 1;
myMap("stuff2") = 2;
myMap("stuff3") = 3;
Thanks
There is no such firstWhereOrNull method for Maps, but you can easily come up with one using extension methods:
extension ExtendedMap on Map {
/// The first entry satisfying test, or null if there are none.
MapEntry? firstWhereOrNull(bool Function(MapEntry entry) test) {
for (var entry in this.entries) {
if (test(entry)) return entry;
}
return null;
}
}
Here is how you can use it:
final map = <String, int>{
'stuff1': 1,
'stuff2': 2,
'stuff3': 3,
};
final test = map.firstWhereOrNull((entry) => entry.value == 2);
print(test); // Prints MapEntry(stuff2: 2)
final nullTest = map.firstWhereOrNull((entry) => entry.key == "stuff5");
print(nullTest); // Prints null
So, I created this implementation, I don't think it's the most optimized, also because it was necessary to use the cast since because of the sound null safety, it's not possible to return any value. But it works for you.
var myMap = {"key1": "value", "key2": 3};
var result = myMap.entries
.cast<dynamic>()
.firstWhere((e) => e.key == "key", orElse: () => null);
print(result);
I hope this helps in some way!

Default value for parameter of Function type in Dart

Consider a function in Dart file
void myFunction({int input = 1, Function(int, String) callback}) {
// ...
}
So, I wonder is it possible at all to specify a default value for the callback parameter, for instance it can be something like (_, _) => { }.
P.S. I know it has null as default value and ?? can help to avoid NPE, I'm just curious is it possible at all. Cheers.
You can do something like:
dynamic func(int i, String s) {
print(i.toString() + s);
}
void myFunction({int input = 1, Function(int, String) callback = func}) {
callback(input, " .");
}
void main() {
myFunction(input: 2);
}
The default value of an optional parameter must be constant.
This is what the documents said
This thing can be bypassed like this:
dynamic myCallback(int a,String b) {
}
void myFunction({int input = 1, Function(int, String) callback }) {
if (callback == null) callback = myCallback;
}
Edit:
Alternatively, you can use anonymos functaion with out myCallback funcation like this:
void myFunction({int input = 1, Function(int, String) callback }) {
if (callback == null) callback = (a,b){};
}

Dart: convert Map to List of Objects

Did several google searches, nothing helpful came up. Been banging my head against some errors when trying to do something that should be pretty simple. Convert a map such as {2019-07-26 15:08:42.889861: 150, 2019-07-27 10:26:28.909330: 182} into a list of objects with the format:
class Weight {
final DateTime date;
final double weight;
bool selected = false;
Weight(this.date, this.weight);
}
I've tried things like: List<Weight> weightData = weights.map((key, value) => Weight(key, value));
There's no toList() method for maps, apparently. So far I'm not loving maps in dart. Nomenclature is confusing between the object type map and the map function. Makes troubleshooting on the internet excruciating.
Following on Richard Heap's comment above, I would:
List<Weight> weightData =
mapData.entries.map( (entry) => Weight(entry.key, entry.value)).toList();
Don't forget to call toList, as Dart's map returns a kind of Iterable.
List<Weight> weightData = List();
weights.forEach((k,v) => weightData.add(Weight(k,v)));
Sometimes the typecast will fail and you can enforce it by doing:
List<Weight> weightData =
weightData.entries.map<Weight>( (entry) => Weight(entry.key, entry.value)).toList();
Example from my project where it wasn't working without typecast:
List<NetworkOption> networkOptions = response.data['data']['networks']
.map<NetworkOption>((x) => NetworkOption.fromJson(x))
.toList();
Use the entries property on the map object
This returns a List of type MapEntry<key,value>.
myMap.entries.map((entry) => "${entry.key} + ${entry.value}").toList();
You can also use a for collection to achieve the same.
var list = [for (var e in map.entries) FooClass(e.key, e.value)];
Details
Flutter 1.26.0-18.0.pre.106
Solution
/libs/extensions/map.dart
extension ListFromMap<Key, Element> on Map<Key, Element> {
List<T> toList<T>(
T Function(MapEntry<Key, Element> entry) getElement) =>
entries.map(getElement).toList();
}
Usage
import 'package:myApp/libs/extensions/map.dart';
final map = {'a': 1, 'b': 2};
print(map.toList((e) => e.value));
print(map.toList((e) => e.key));
You can do this:
List<Weight> weightData = (weights as List ?? []).map((key, value) => Weight(key,value)).toList()
or you can try:
List<Weight> weightData = List.from(weights.map((key, value) => Weight(key, value)))
If you need to convert Map values to a list, the simplest oneline code looks like this:
final list = map.values.toList();
Vidor answer is correct .any way this worked for me
List<String> list = new List();
userDetails.forEach((k, v) => list.add(userDetails[k].toString()));
its very simple just initialize a list of your custom object like this
List<CustomObject> list=[];
for (int i = 0; i < map.length; i++) {
CustomObject customObject= CustomObject(
date:map[i]['key'],
weight:map[i]['key']
);
list.add(CustomObject);
}
hope it works for you thanks
You simply don't need to. the values property is an Iterable<> of your objects. You can iterate over this or you can convert it to a list. For example,
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets("convert Map to List of Objects", (tester) async {
final weight1 = Weight(const ValueKey("1"), DateTime.now(), 1);
final weight2 = Weight(const ValueKey("2"), DateTime.now(), 2);
final map = {weight1.key: weight1, weight2.key: weight2};
//You don't have to convert this to a list
//But you can if you want to
final list = map.values.toList();
list.forEach((w) => print("Key: ${w.key} Weight: ${w.weight} "));
});
}
class Weight {
final Key key;
final DateTime date;
final double weight;
bool selected = false;
Weight(this.key, this.date, this.weight);
}
Object Class
class ExampleObject {
String variable1;
String variable2;
ExampleObject({
required this.variable1,
required this.variable2,
});
Map<String, dynamic> toMap() {
return {
'variable1': this.variable1,
'variable2': this.variable2,
};
}
factory ExampleObject.fromMap(Map<String, dynamic> map) {
return ExampleObject(
variable1: map['variable1'] as String,
variable2: map['variable2'] as String,
);
}
}
Convert Map to Object List
List<ExampleObject> objectList = List<ExampleObject>.from(mapDataList.map((x) => ExampleObject.fromMap(x)));