Dart Как отфильтровать карту по ключам - PullRequest
0 голосов
/ 20 июня 2020

Как обрабатывать карту на основе ключей?

Если на моей карте ключ равен моей переменной, тогда я хочу создать список, содержащий мою карту

Если в моем сопоставить ключ не равен моей переменной; тогда я хочу создать список, содержащий 2 объекта карты с ключом, имеющим ближайшее меньшее значение, и ключом с ближайшим более высоким значением

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
    };

Для примера с myVar = 100 я хочу иметь это:

int myVar = 100;
 
  Map values = {
      "100"   : -22,
    };

И если myVar = 112, например, мне нужно иметь ближайшие значения ключей. Мой результат должен быть:

Map values = {
      "100"   : -22,
      "200"   : -43,
    };

Я не знаю, как это сделать. Возможно, мне пришла идея преобразовать карту в список карт, чтобы иметь возможность использовать функции списка.

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();

это правильный метод? Как преобразовать мою карту basi c, если да?

EDIT : Я пробовал это с помощью @jamesdlin, но у меня возникла ошибка.

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));
}

У меня на дартпаде есть:

: 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>'

1 Ответ

1 голос
/ 20 июня 2020

По умолчанию Map - это LinkedHashMap, где порядок итерации - это порядок вставки ключей. Для вашего использования вместо этого вы, вероятно, захотите использовать SplayTreeMap, где поиск - это O (log n) вместо (в идеале) O (1) (WRT количество элементов), но порядок итераций в порядке возрастания ключей. Это позволит вам использовать методы lastKeyBefore(key) и firstKeyAfter(key) для поиска предыдущего и следующего элементов, если ключ напрямую не содержится.

Я также рекомендовал бы вам использовать int в качестве ключа вместо String. Если вы используете String, порядок по умолчанию будет следующим: лексикографи c порядок ("1" <<code>"10" <<code>"100" <<code>"2"). Вы можете предоставить свой собственный обратный вызов сравнения для SplayTreeMap для синтаксического анализа String s на int s при сравнении, но это все равно потребует синтаксического анализа одних и тех же String s несколько раз. Было бы намного проще и эффективнее хранить int s как ключи напрямую.

Используя int ключи с SplayTreeMap, это будет выглядеть примерно так:

Map<int, int> filter(int myVar, SplayTreeMap<int, int> values) {
  if (values.contains(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],
  };
}
...