背景

我希望能够制作一个SplayTreeMap,键是元组,值是映射列表.它看起来如下所示:

{
   (1, 2023): [
         {
            "id": 1,
            "name": "Bob"
         },
         {
            "id": 2,
            "name": "Alice"
         },
    ],
   (3, 2023): [
         {
            "id": 3,
            "name": "Charlie"
         },
         {
            "id": 4,
            "name": "Diana"
         },
    ]
}

到目前为止,我只是在试验dart 垫,以确保我得到了正确的,我认为以下工作应该是有效的.

import 'dart:collection';

void main() {
  var invoicesST = SplayTreeMap();

  for(int i = 0; i < 10; i++) {
  invoicesST[(i, i+2000)] = [];

      invoicesST.update(
          [(i, i+2000)],
          (value) => [
                ...invoicesST[(i, i+2000)],
                {
                  'scId': 'sc$i',
                  'year': i+2000,
                  'week': i,
                  'month': i
                }
              ]);
    
          invoicesST.update(
          [(i, i+2000)],
          (value) => [
                ...invoicesST[(i, i+2000)],
                {
                  'scId': 'sc$i',
                  'year': i+2000,
                  'week': i+1,
                  'month': i
                }
              ]);
  }
  
  print(invoicesST);
}

但输出是错误 TypeError: Record (0, 2000): type '(int, int)' is not a subtype of type 'Comparable<dynamic>'Error: TypeError: Record (0, 2000): type '(int, int)' is not a subtype of type 'Comparable<dynamic>'.所以我猜记录不会延长到Comparable年?

我认为我应该做自己的,并做了以下操作,但最终还是犯了同样的错误.

class MonthYear<T1, T2> {
  final T1 month;
  final T2 year;

  MonthYear(this.month, this.year);
  
  @override
  bool operator ==(other) {
    return (other is MonthYear)
        && other.month == month
        && other.year == year;
  }
  
  @override
  int get hashCode => month.hashCode ^ year.hashCode;
}

问题

有没有办法让这件事奏效,或者至少有类似的办法?我不赞成使用Record类型,但它最初似乎是最好的.

边注

我使用SplayTreeMap是因为我希望能够按降序对键进行排序.

EDIT:

我突然想到,我可以使用DateTime作为关键字,但我的数据仍然是...is not a subtype of Comparable


最终结果

请阅读@jamesdlin的the marked solution,那里有这么多有用的信息.我想我应该添加我为保持一致性而确定的代码.

import 'dart:collection';

void main() {
  var invoicesST = SplayTreeMap<DateTime, List>();

  for(int i = 0; i < 10; i++) {
  invoicesST[DateTime(i+2000, i)] = [];

    invoicesST.update(
        DateTime(i+2000, i),
        (value) => [
              ...(invoicesST[DateTime(i+2000, i)] ?? []),
              {'scId': 'sc$i', 'year': i + 2000, 'week': i, 'month': i}
            ]);
    
        invoicesST.update(
        DateTime(i+2000, i),
        (value) => [
              ...(invoicesST[DateTime(i+2000, i)] ?? []),
               {'scId': 'sc$i', 'year': i + 2000, 'week': i + 1, 'month': i}
            ]);
  }
  
  print(invoicesST);
}

DateTime被用作密钥,但我不正确地使用它,就像EDIT中提到的那样,我使用update()的方式也不正确.

推荐答案

AS pskink explained in a commentSplayTreeMap或者期望密钥是Comparable,或者期望SplayTreeMap是用显式比较函数构造的.因此,您可以执行以下操作:

import 'dart:collection';

typedef MonthYear = (int, int);

int compareMonthYear(MonthYear monthYear1, MonthYear monthYear2) {
  var (month1, year1) = monthYear1;
  var (month2, year2) = monthYear2;

  if (year1 < year2) {
    return -1;
  } else if (year1 > year2) {
    return 1;
  }

  if (month1 < month2) {
    return -1;
  } else if (month1 > month2) {
    return 1;
  }

  return 0;
}

void main() {
  var invoicesST = SplayTreeMap<MonthYear, List>(compareMonthYear);

  for (int i = 0; i < 10; i++) {
    invoicesST[(i, i + 2000)] = [];

    invoicesST.update(
        (i, i + 2000),
        (value) => [
              ...(invoicesST[(i, i + 2000)] ?? []),
              {'scId': 'sc$i', 'year': i + 2000, 'week': i, 'month': i}
            ]);

    invoicesST.update(
        (i, i + 2000),
        (value) => [
              ...(invoicesST[(i, i + 2000)] ?? []),
              {'scId': 'sc$i', 'year': i + 2000, 'week': i + 1, 'month': i}
            ]);
  }

  print(invoicesST);
}

我对代码进行了其他一些更正,特别是:

  • SplayTreeMap构造函数添加了显式类型参数.
  • invoicesST.update的调用不正确地将MonthYear条记录包装在List中.
  • invoicesST[(i, i + 2000)]查找可能会失败并返回null,并且您不能对其使用扩散运算符(...).

我认为我应该做自己的,并做了以下操作,但最终还是犯了同样的错误.

显式的MonthYear类实现完全忽略了实现Comparable接口(如错误消息所解释的).您可以通过提供显式比较回调来修复该问题,或者,因为您控制了MonthYear类:

class MonthYear<T1, T2> implements Comparable<MonthYear> {
  ...

  @override
  int compareTo(MonthYear other) {
    if (year < other.year) {
      return -1;
    } else if (year > other.year) {
      return 1;
    }

    if (month < other.month) {
      return -1;
    } else if (month > other.month) {
      return 1;
    }

    return 0;
  }
}

(另请参阅Sort a list of objects in Flutter (Dart) by property value.)

请注意,上面的比较函数将按ascending的顺序对日期进行排序.如果您想要降序,您可以让比较函数返回取反的值,或者您也可以反转输出.

我突然想到,我可以使用DateTime作为关键字,但我的数据仍然是...is not a subtype of Comparable

您还没有展示使用DateTime的try ,但是DateTime does实现了Comparable接口,所以您做了其他错误的事情:

import 'dart:collection';

void main() {
  var map  = SplayTreeMap<DateTime, String>();
  map[DateTime(2000, 1, 1)] = 'Hello';
  map[DateTime(2001, 1, 2)] = 'world';
  print(map);
}

Flutter相关问答推荐

Riverpod生成器和生成util类

如何在用Ffltter成功登录后重定向下一页?

从超级应用程序启动时,Flutter 小应用程序中未加载资源

如何将请求字段正确添加到DART多部分请求

在 flutter 吧蜂巢中拯救主题

Flutter为什么不;没有ListView.iterable()构造函数?

在带有 flutter 的 Native Android 中,EventChannel.EventSink 始终为 null

TextField 中的富文本并获取 RenderParagraph

在 Flutter 中使用条件语句设置 ImageProvider Object 类型的背景图像

Flutter中如何实现带有变化图标的浮动操作按钮?

更改 flutter listview 中的布局

我可以在列表图块下方添加其他小部件吗

更改底部导航栏下方 Flutter Snackbar 的位置

Elevated 和 Outlined 按钮之间的动画

面对Flutter 中的行和列问题

Android: 从 URI 获取音频元数据

有没有办法为文本中的下划线创建自定义样式?

Flutter 将方法应用于静态变量

参数类型MaterialPageRoute不能分配给参数类型String

如何在 IntroductionScreen 小部件 Flutter 中制作全屏渐变色