Home > database >  Dart Map keys, get unique key
Dart Map keys, get unique key

Time:12-03

Simple Map here:

Map map = Map<int, String>{};

I can populate it:

map = {1: 'c', 2: 'dart', 3: 'flutter'};

Here I need to specify a KEY. I would like to know on how to get an auto key.

I cannot use map.lenght because whenever I will delete e.g. the second item (2) the third will remain 3 and map.lenght will overwrite that key.

As the @eamirho3ein answer I tried this:

  //& Maps
  Map map = <int, Ingredient>{};


Map addToMap<Ingredient>(
    Map<int, Ingredient> map, Ingredient newItem) {
  var list = map.entries.map((e) => e.value).toList();
  list.add(newItem);
  var newIndex = 1;

  return Map.fromIterable(list,
      key: (item) => newIndex  , value: (item) => item);
}


var result = addToMap<Ingredient>(
                            map, //Error here
                            Ingredient(
                                name: "Pizza",
                                kcal: 100,
                                carbohydrates: 50,
                                proteins: 35,
                                lipids: 23,
                                fibers: 12,
                                date: DateTime.now(),
                                bottomTabIndex: 0,
                                leftTabIndex: 0));

But I receive this error on map(indicated):

The argument type 'Map<dynamic, dynamic>' can't be assigned to the parameter type 'Map<int, Ingredient>'.

This is my simple class:

class Ingredient {
  String? name;
  int? kcal;
  int? carbohydrates;
  int? proteins;
  int? lipids;
  int? fibers;
  int? leftTabIndex;
  int? bottomTabIndex;
  DateTime? date;

  Ingredient(
      {this.name,
      this.kcal,
      this.carbohydrates,
      this.proteins,
      this.lipids,
      this.fibers,
      this.leftTabIndex,
      this.bottomTabIndex,
      this.date});
}

CodePudding user response:

You can use an incrementing index key that will be always different than others on every call, and wrapping it inside an autoKey() method like this:

int index = 0;
autoKey() {
  return   index;
}

Map<int, String> map = {};
map = {autoKey(): 'c', autoKey(): 'dart', autoKey(): 'flutter'};

print(map); {1: c, 2: dart, 3: flutter}

CodePudding user response:

Maybe I should use a function:

int getNewKey(Map map) {
  if (map.isEmpty) {
    return 0; // or 1, this is the first item I insert
  } else {
    return map.keys.last   1;
  }
}

And use it whenever I will add something to that map:

{getNewKey(map) : 'c', getNewKey(map) : 'dart', getNewKey(map) : 'flutter'}

Please let me know if this is faulty :-|

By this way I will never overwrite a key that's only incremental.

Please note: I should not use directly

{(map.keys.last   1) : 'c', (map.keys.last   1) : 'dart', (map.keys.last   1) : 'flutter'}

Because if the Map is empty will produce an error.

CodePudding user response:

another way is that you can use a class as key that never equals itself using hashCode, like this:

class nonEqualKey {
  
  @override
  int get hashCode => 0;
  
  @override
  operator ==(covariant nonEqualKey other) {
    return other.hashCode != hashCode;
  }
  @override
  toString() {
    return "unique";
  }
}

Map map = {};
map = {nonEqualKey(): 'c', nonEqualKey(): 'dart', nonEqualKey(): 'flutter'};
print(map); // {unique: c, unique: dart, unique: flutter}

Here I overridden the hashCode so it will be always 0, then I overridden the == operator so the objects can be equal if they have a different hashCode which is impossible since always 0!=0 is false.

Even if you use the same class constructor, they will never be the same, and so, it lets you use it as much as you want without needing to handle it for every operation you will do on the Map

CodePudding user response:

You can use this function to remove an item in a map and auto generate new key:

Map<int, T> removeFromMap<T>(Map<int, T> map, int index) {
    var list = map.entries.map((e) => e.value).toList();
    list.removeAt(index);
    var newIndex = 1;

    return Map.fromIterable(list,
        key: (item) => newIndex  , value: (item) => item);
  } 

you can use it like this:

var result = removeFromMap<String>({1: 'c', 2: 'dart', 3: 'flutter'}, 1);
print("result = $result"); //result = {1: c, 2: flutter}

If you want add new Item:

Map<int, T> addToMap<T>(Map<int, T> map, T newItem) {
    var list = map.entries.map((e) => e.value).toList();
    list.add(newItem);
    var newIndex = 1;

    return Map.fromIterable(list,
        key: (item) => newIndex  , value: (item) => item);
  }

and call it like this:

var result = addToMap<String>({1: 'c', 2: 'dart', 3: 'flutter'}, 'B');
print("result = $result"); //result = {1: c, 2: dart, 3: flutter, 4: B}
  • Related