flutter 使用记录/元组作为SplayTreeMap中的键

ippsafx7  于 2023-11-21  发布在  Flutter
关注(0)|答案(1)|浏览(106)

后台

我希望能够制作一个SplayTreeMap,键是元组,值是一个Map列表。它看起来像下面这样:

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

提问

有没有一种方法可以让这个工作或至少类似的东西?我不结婚的想法使用记录类型,但它似乎是最好的最初。

卫星

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

编辑:

我刚刚想到,我可以使用DateTime作为我的数据的方式,但再次...is not a subtype of Comparable相同的错误的关键

结束结果

请阅读the marked solution by @jamesdlin,那里有很多有用的信息。我想我会添加我决定的代码以保持一致性。

import 'dart:collection';

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

  for(int i = 0; i < 10; i++) {
  var example = {'scId': 'sc$i', 'year': i + 2000, 'week': i, 'month': i};

    invoicesST.update(
        DateTime(i+2000, i),
        (value) => [
              ...(invoicesST[DateTime(i+2000, i)] ?? []), example
            ], ifAbsent: () => [example]);
  }
  
  print(invoicesST);
}


一个DateTime被用作密钥,但我在 EDIT 中提到的使用它的方式以及我使用update()的方式是错误的。

mwg9r5ms

mwg9r5ms1#

正如pskink在评论中解释的那样,SplayTreeMap要么期望键是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记录 Package 在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;
  }
}


(Also参见Sort a list of objects in Flutter (Dart) by property value。)
请注意,上面的比较函数将按 * 升序 * 对日期进行排序。如果你想要降序,你可以让比较函数返回否定值,或者你可以反转输出。
我刚刚想到,我可以使用DateTime作为我的数据的方式,但再次...is not a subtype of Comparable相同的错误的关键
您还没有尝试使用DateTime,但是DateTime * 确实 * 实现了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);
}

相关问题