user2895656
user2895656

Reputation: 57

Dart How to filter a map by keys

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

Answers (1)

jamesdlin
jamesdlin

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 Strings into ints when comparing, but doing so would still require parsing the same Strings multiple times. It'd be much simpler and more efficient to store ints 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

Related Questions