Reputation: 57
How to handle a map based on the keys?
If in my map the key is equal to my variable then I want to create a list which contains my map
If in my map the key is not equal to my variablecthen I want to create a list which contains 2 map objects with the key which has the nearest lower value and the key which has the nearest higher value
int myVar = 100;
Map values = {
"-900" : 183,
"-800" : 164,
"-700" : 144,
"-600" : 124,
"-500" : 104,
"-400" : 84,
"-300" : 63,
"-200" : 42,
"-100" : 21,
"0" : 0,
"100" : -22,
"200" : -43,
"300" : -64
};
For the exemple with myVar = 100, I want to have this:
int myVar = 100;
Map values = {
"100" : -22,
};
And if myVar = 112 for exemple I need to have the closest keys values. My result must be :
Map values = {
"100" : -22,
"200" : -43,
};
I don't know how to do that.I had perhaps the idea to transform the map into a map list to be able to use the list functions.
List<Map> values = [
{
"arg1" :-900,
"arg2": 183
},
{
"arg1" :-800,
"arg2": 164
},
{
"arg1" :-700,
"arg2": 144
},
// Some other values ...
];
List newValues = values.where((c) => c['arg1'] == 100).toList();
is this the right method? How to transform my basic map if yes ?
EDIT : With the help of @jamesdlin I tried this but I have an error.
import 'dart:collection';
void main() {
int myVar = 100;
Map<int, int> values = {
-900 : 183,
-800 : 164,
-700 : 144,
-600 : 124,
-500 : 104,
-400 : 84,
-300 : 63,
-200 : 42,
-100 : 21,
0 : 0,
100 : -22,
200 : -43,
300 : -64
};
print(values);
Map<int, int> filter(int myVar, SplayTreeMap<int, int> values) {
if (values.containsKey(myVar)) {
return {myVar: values[myVar]};
}
int lowerKey = values.lastKeyBefore(myVar);
int upperKey = values.firstKeyAfter(myVar);
return {
if (lowerKey != null) lowerKey: values[lowerKey],
if (upperKey != null) upperKey: values[upperKey],
};
}
print(filter(myVar, values));
}
I have this on dartpad :
: TypeError: Instance of 'JsLinkedHashMap<int, int>': type 'JsLinkedHashMap<int, int>' is not a subtype of type 'SplayTreeMap<int, int>'Error: TypeError: Instance of 'JsLinkedHashMap<int, int>': type 'JsLinkedHashMap<int, int>' is not a subtype of type 'SplayTreeMap<int, int>'
Upvotes: 1
Views: 3266
Reputation: 89936
By default, Map
is a LinkedHashMap
, where iteration order is key insertion order. For your use, you instead probably will want to use a SplayTreeMap
where lookups are O(log n) instead of (ideally) O(1) (WRT the number of elements), but iteration order is in ascending order of keys. This would allow you to use the lastKeyBefore(key)
and firstKeyAfter(key)
methods to find the previous and next elements if the key isn't directly contained.
I also would recommend that you use int
as the key instead of a String
. If you use a String
, the default ordering will be a lexicographic order ("1"
< "10"
< "100"
< "2"
). You could supply you own comparison callback to SplayTreeMap
to parse String
s into int
s when comparing, but doing so would still require parsing the same String
s multiple times. It'd be much simpler and more efficient to store int
s as the keys directly.
Using int
keys with a SplayTreeMap
, it'd look something like:
import 'package:collection/collection.dart'; // For SplayTreeMap
Map<int, int> filter(int myVar, SplayTreeMap<int, int> values) {
if (values.containsKey(myVar)) {
return {myVar: values[myVar]};
}
int lowerKey = values.lastKeyBefore(myVar);
int upperKey = values.firstKeyAfter(myVar);
return {
if (lowerKey != null) lowerKey: values[lowerKey],
if (upperKey != null) upperKey: values[upperKey],
};
}
Upvotes: 1