Antonin GAVREL
Antonin GAVREL

Reputation: 11219

Flutter dart Map with multiple keys for very same value

Is there any kind of collection to declare a map with multiple keys linked to the very same value ?

I want the map to be initialized at the same time that it is declared. Ideally something like:

MyMap<String, String> mymap = {['red', 'blue', 'green'] : 'Rock', ['pink', 'yellow' ...etc}

So far I found Multimap in the documentation but it seems that its one key for multiple value, and on top of that I have a lot of trouble for implementing since that despite the documentation there is 0 example given.

Here my try so far:

static Iterable mylist = ['red', 'blue', 'green']; // I want to associate these strings to 'Rock'
static Iterable mylist = ['pink', 'yellow', 'cyan']; // I want to associate these strings to 'Funk'
static Multimap<String,String> okayboomer = Multimap.fromIterable(mylist);//, {K key(dynamic element), V value(dynamic element)});

And then whenever I access okayboomer['red'] I would get 'Rock'.

I was also thinking about HashMap

Any help strongly appreciated!

Upvotes: 6

Views: 14654

Answers (3)

jamesdlin
jamesdlin

Reputation: 89975

You don't necessarily need any special data structure; a normal Map can have multiple keys for the same value, and you just need a helper function to make initializing it more convenient:

Map<String, String> makeMyMap(Map<List<String>, String> map) {
  var newMap = <String, String>{};
  for (var entry in map.entries) {
    var keyList = entry.key;
    for (var key in keyList) {
      newMap[key] = entry.value;
    }
  }
  return newMap;
}

and then you should be able to do:

var mymap = makeMyMap({
  ['red', 'blue', 'green'] : 'Rock',
  ['pink', 'yellow', 'cyan']: 'Funk',
});

Note that the above Map would work for lookups, and if you mutated values in the map, the related keys would still refer to the same object. If, however, you need to replace values in the map, related keys would continue referring to the old object. If you need to do that, you would need to add a level of indirection around the values. For example:

class Wrapped<T> {
  Wrapped(this.value);
  T value;
}

var map = <String, Wrapped<String>>{};
map['red'] = map['blue'] = map['green'] = Wrapped('Rock');
map['red'].value = 'Funk';
print(map['blue'].value); // Prints: Funk

You could derive a class from DelegatingMap to automatically unwrap values when using operator [] and to automatically update existing Wrapped objects for operator []=.

Upvotes: 4

Shubham Gupta
Shubham Gupta

Reputation: 1997

Since you want the map to be initialized at the same time that it is declared, you can simply do it this way

 Map<List<String>,dynamic> x = {
  ['red', 'blue', 'green']:"ROCK",
  ['pink', 'yellow', 'cyan']:"FUNK"
 };
 

And then access the values by iterating over keys and the List,

print(x[x.keys.firstWhere((value)=>value.contains("red"))]);

Upvotes: -1

Alex Collette
Alex Collette

Reputation: 1784

I agree with jamesdlin's answer, you should be able to just assign duplicate values to multiple keys. However, depending on your use case, this may not work for you. If you want to change the value associated with the key 'red', it will not update the listings associated with 'blue' and 'green'

If this type of integrity is important to you, I would store all of your values in a list, or a secondary map, and then store references to them in the primary map. That way, if you update any of the keys, it will change the values for all of them.

Upvotes: 0

Related Questions