I want to check if an array of maps contains a specific map.
void main() {
List<Map> mapArray = [{"a":1,"b":1}];
print(mapArray.contains({"a":1,"b":1})); // prints false
}
Even though the mapArray array contains that {"a":1,"b":1} map, mapArray.contains function will return false.
I've found a solution by converting the maps into strings and checking if the array contains that string.
print(mapArray.map((x)=>x.toString()).contains({"a":1,"b":1}.toString())); // prints true
However, this doesn't look like the best solution. Please let me know if there is a better workaround for this issue.
You can use the equals method of DeepCollectionEquality:
import 'package:collection/collection.dart';
void main() {
List<Map> mapArray = [{"a":1,"b":1}, {"c":25,"d":99}];
print(mapArray.any((element) => DeepCollectionEquality().equals(element, {"a":1,"b":1})));
}
Related
I have heard that all data types in dart are reference types, but some fairly primitive ones such as int behave as value types. Does Map behave as a value type?
I had wrapped a class around my Map and it worked:
final manageVgnItmFormsProvider = Provider.autoDispose<VgnItmForms>((provider) {
return VgnItmForms();
});
class VgnItmForms {
late Map<String, VgnItmFormVm> forms;
VgnItmForms();
}
And I changed it to:
final manageVgnItmFormsProvider = Provider.autoDispose<Map>((provider) {
var forms = {};
return forms;
});
And then the forms Map kept going back to being an empty Map after I had set it to a populated Map elsewhere. I think it is getting lost because Map is treated as a value type and before my class was treated as a reference type.
Imagine you have the following json
{
"list": [
["xa", "yc", "ze"],
["xb", "yd", "zf"]
]
}
how do we convert this to a List<List<String>> with json.decode() in dart?
I'm going to make the assumption that this is a string before you pass it to jsonDecode, which will return a Map<String, dynamic>.
// The original string
String jsonString = "{\"list\": [[\"xa\", \"yc\", \"ze\"], [\"xb\", \"yd\", \"zf\"]]}";
// The parsed map
Map<String, dynamic> json = jsonDecode(jsonString);
Now, it seems like you don't care about the containing Map.
Technically, those things that look like Lists are actually Maps at this point, so those type assertions would fail.
List<List<String>> output = json["list"].map((value) => value.toList()).toList();
That's the most straightforward method I can think of right now.
I'm trying to convert this map {[string1,string2]}
in to an array like this
[string1, string2]
in dart
A declaration of that kind in Dart is a Set(which is like a list but cannot have duplicates) of Lists, given that to get the first value you should just use
obj.first
(Sets are declared like maps but without any key)
This is a Set.
So you can do this for convert it to list:
Set<List<String>> map = {['string1','string2']};
List list = [];
map.forEach((k) {
k.forEach((item) => list.add(item));
});
as already mentioned in other answers this is a Set
you can easy convert it to List like this
var mySet = {['string1', 'string2']};
var list = mySet.expand((e) => e).toList();
print(list); // [string1, string2]
The 'map' you gave has one key (list of strings), which seems to be missing a value.
If your map looked something like this:
Map<List<String>, int> map = {[string1,string2]: 0};
Then you could get an Iterable of your keys (or values if you wish) with:
dynamic temp = map.keys //for the keys or
//or temp = map.values //for the values
You can further convert that Iterable into a List by calling the function toList() on it:
List<String> myList = temp.toList();
I hope this answered your question.
And if you are not sure what the type of your object is, use:
print(yourObject.runTimeType);
How to select random key (element) from Map?
I can do it using map.keys.toList(), as in the code below, but I wonder if there is more direct way?
import "dart:math";
void main() {
var map = {'a' :1, 'b':2, 'c':3};
final _random = new Random();
var keys = map.keys.toList();
var element = keys[_random.nextInt(keys.length)];
var r = map[element];
print(r);
}
There is no simple way to pick a "random" key from a map.
I assume that "random" here means to pick it uniformly at random among the keys of the map.
For that, you need to pick a random number in the range 0..map.length - 1. Then you need to get the corresponding key. Since Map.key is an iterable, you can't assume that you can do constant-time lookup in it, but you can use elementAt to get a specific iterable item without creating a new list.
So, basically:
randomKey(Map map) =>
map.keys.elementAt(new Random().nextInt(map.length));
(like you do it, but without the toList).
If you need more than one key, you are probably better off converting the keys to a list once, and then do lookups in the list in constant time. Example:
Iterable randomKeys(Map map) sync* {
var keys = map.keys.toList();
var rnd = new Random();
while (keys.length > 0) {
var index = rnd.nextInt(keys.length);
var key = keys[index];
keys[index] = keys.last;
keys.length--;
yield key;
}
}
On top of getting better performance, taking a copy of the keys also avoids concurrent modification errors.
If you are selecting multiple random values from the list and you want to make sure you never select an entry more than once, you can take the keys or values as a list, shuffle it then iterate through it.
This is not very efficient if only a small fraction of the entries in the map are to be selected.
void main() {
var map = { 'a' :1, 'b':2, 'c':3 };
// Keys
var keys = map.keys.toList()..shuffle();
for(var k in keys) {
print('$k, ${map[k]}');
}
// Values
var values = map.values.toList()..shuffle();
for(var v in values) {
print(v);
}
}
https://dartpad.dartlang.org/e49012d93f7451af1662ad113f0aab95
I guess this is not what you're looking for, but actually it's a line shorter ;-)
void main() {
var map = {'a' :1, 'b':2, 'c':3};
final _random = new Random();
var values = map.values.toList();
var element = values[_random.nextInt(values.length)];
print(element);
}
DartPad example
You can use the dart_random_choice package to help you. While Map itself is not an iterable, you can use the Map.keys method to get an iterable and do the following:
import 'package:dart_random_choice/dart_random_choice.dart';
void main() {
var map = { 'a': 1, 'b': 2, 'c':3 };
var r = map[randomChoice(map.keys)];
print(r);
}
I have a question.
When working with Dart, I can't check to see if 2 arrays are equal.
(in other languages, I can do with ==)
In fact, I just can do that == with String or number.
List arr1 = [1,2,3];
List arr2 = [1,2,3];
if (arr1 == arr2) {
print("equal");
} else {
print("not equal");
}
// Output: not equal.
So I wonder how does that make sense. I mean, How we can do if the == is just work for the cases of String or number (if the values compared are the same).
How do I have to do if I want to check that kind of comparison (equal) for List, Map, ..
It just work for String & number.
arr1 and arr2 are different instances of an object of type List. By default different instances are always different.
When a class implements a custom == operator it can override this behavior. Some classes have a custom implementation by default like int and String.
This can easily be done for immutable objects but not for mutable. One reason is that usually the hashCode is calculated from the values stroed in a class and the hashCode must not change for an instance because this can for example cause that an instance stored in a map can't be retrieved anymore when the hashcode of the key changed.
As a workaround there is a library that provides helper functions to compare lists/iterables.
import 'package:collection/equality.dart';
void main(List<String> args) {
if (const IterableEquality().equals([1,2,3],[1,2,3])) {
// if (const SetEquality().equals([1,2,3].toSet(),[1,2,3].toSet())) {
print("Equal");
} else {
print("Not equal");
}
}