首页 > 解决方案 > Dart 为什么我的代码不适用于负值

问题描述

我尝试了一个小代码,但我有一个无法解释的奇怪行为。

我想根据一个值返回基于键的映射的“键值”。我的代码具有正值。如果该值不在数组中,则返回 null。

仅当值包含在我的数组中时,它也适用于负值。如果我输入一个低于我的数组的负值,那么它返回的不是空值而是零,这是错误的!

我的地图中的键必须是字符串。

我可以在 dartPad 上测试的代码:

import 'dart:collection';

void main() {

  int myVar = -360;

  Map<String, dynamic> values = {
      "-200"  : 42,
      "-100"  : 21,
      "0"     : 0,
      "100"   : -22,
      "150"   : -30,
      "200"   : -43,
      "300"   : -64
    };  
 
  Map<String, dynamic> filter(int myVar, Map<String, dynamic> values) {
    
    SplayTreeMap<String, dynamic> newval = SplayTreeMap.of(values);
    String convertString = myVar.toString();
    
    if (values.containsKey(convertString)) {
      return {convertString: values[convertString]};
    }
    
    String lowerKey;
    String upperKey;
    
    if(myVar > 0){
      lowerKey = newval.lastKeyBefore(convertString);
      upperKey = newval.firstKeyAfter(convertString);  
    }
    else{
      lowerKey = newval.firstKeyAfter(convertString);
      upperKey = newval.lastKeyBefore(convertString);
    }
    
    print(lowerKey);
    print(upperKey);
    
    return {
      if (lowerKey != null) lowerKey: values[lowerKey],
      if (upperKey != null) upperKey: values[upperKey],
    };
    
  }
  
  var result = filter(myVar, values);
  print('============================');
  print(result);
}

标签: dart

解决方案


首先,我想对代码中的使用提出一个小小的抱怨dynamicdynamic在 JSON 解析等运行时无法确定类型的情况下使用它是完全可以的。但是在这种情况下,所有的类型都可以确定,dynamic不需要使用。所以我已经修复了代码以删除使用dynamic并删除了不必要的输入:

import 'dart:collection';

void main() {
  const myVar = -360;

  final values = {
    "-200": 42,
    "-100": 21,
    "0": 0,
    "100": -22,
    "150": -30,
    "200": -43,
    "300": -64
  };

  Map<String, int> filter(int myVar, Map<String, int> values) {
    final newVal = SplayTreeMap.of(values);
    final convertString = myVar.toString();

    if (values.containsKey(convertString)) {
      return {convertString: values[convertString]};
    }

    String lowerKey;
    String upperKey;

    if (myVar > 0) {
      lowerKey = newVal.lastKeyBefore(convertString);
      upperKey = newVal.firstKeyAfter(convertString);
    } else {
      lowerKey = newVal.firstKeyAfter(convertString);
      upperKey = newVal.lastKeyBefore(convertString);
    }

    print(lowerKey);
    print(upperKey);

    return {
      if (lowerKey != null) lowerKey: values[lowerKey],
      if (upperKey != null) upperKey: values[upperKey],
    };
  }

  final result = filter(myVar, values);
  print('============================');
  print(result);
}

您的问题是您正在使用SplayTreeMap对密钥进行排序,values但您使用字符串来表示您的数字。这相当令人困惑,因为数字是有效的键。但这也意味着您的排序SplayTreeMap是按字母顺序排列的,而不是按数字排列的。这正是您的代码无法按预期工作的原因。

您可以将键的类型更改为,也可以int提供一种compare方法来SplayTreeMap更改排序的完成方式。

我做了以下示例,其中我更改了int使您的代码工作的键的类型:

import 'dart:collection';

void main() {
  const myVar = -360;

  final values = {
    -200: 42,
    -100: 21,
    0: 0,
    100: -22,
    150: -30,
    200: -43,
    300: -64
  };

  Map<int, int> filter(int myVar, Map<int, int> values) {
    final newVal = SplayTreeMap.of(values);

    if (values.containsKey(myVar)) {
      return {myVar: values[myVar]};
    }

    int lowerKey;
    int upperKey;

    if (myVar > 0) {
      lowerKey = newVal.lastKeyBefore(myVar);
      upperKey = newVal.firstKeyAfter(myVar);
    } else {
      lowerKey = newVal.firstKeyAfter(myVar);
      upperKey = newVal.lastKeyBefore(myVar);
    }

    print(lowerKey);
    print(upperKey);

    return {
      if (lowerKey != null) lowerKey: values[lowerKey],
      if (upperKey != null) upperKey: values[upperKey],
    };
  }

  final result = filter(myVar, values);
  print('============================');
  print(result);
}

输出

-200
null
============================
{-200: 42}

推荐阅读