70

In Dart language how to get MAP keys by values?

I have a Map like;

{
  "01": "USD",
  "17": "GBP",
  "33": "EUR"
}

And I need to use values to get keys. How do I do that?

Machavity
  • 30,841
  • 27
  • 92
  • 100
Nick
  • 4,163
  • 13
  • 38
  • 63

8 Answers8

121
var usdKey = curr.keys.firstWhere(
    (k) => curr[k] == 'USD', orElse: () => null);
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks Günter its working... By the way where I can get details information for this? So I can study to understand and I can use late in my advance Map project? – Nick Aug 28 '18 at 07:30
  • 3
    I don't think this is documented as a thing by itself. There is the `keys` property of `Map` and the `firstWhere` method of `Iterable` and the rest is using them together in a meaningful way. https://api.dartlang.org/stable/2.0.0/dart-core/Map/keys.html, https://api.dartlang.org/stable/2.0.0/dart-core/Iterable/firstWhere.html – Günter Zöchbauer Aug 28 '18 at 07:32
22

If you will be doing this more than a few times on the same data, you should create an inverse map so that you can perform simple key lookup instead of repeated linear searches. Here's an example of reversing a map (there may be easier ways to do this):

main() {
  var orig = {"01": "USD", "17": "GBP", "33": "EUR"};
  var reversed = Map.fromEntries(orig.entries.map((e) => MapEntry(e.value, e.key)));
  for (var kv in reversed.entries) {
    print(kv);
  }
}

Edit: yes, reversing a map can simply be:

var reversed = orig.map((k, v) => MapEntry(v, k));

Tip of the hat to Joe Conway on gitter. Thanks.

Randal Schwartz
  • 39,428
  • 4
  • 43
  • 70
8

There is another one method (similar to Günter Zöchbauer answer):

void main() {

  Map currencies = {
     "01": "USD",
     "17": "GBP",
     "33": "EUR"
  };

  MapEntry entry = currencies.entries.firstWhere((element) => element.value=='GBP', orElse: () => null);

  if(entry != null){
    print('key = ${entry.key}');
    print('value = ${entry.value}');
  }

}

In this code, you get MapEntry, which contains key and value, instead only key in a separate variable. It can be useful in some code.

Makdir
  • 390
  • 2
  • 8
  • This was useful since (element) contains both key & value and helped me in the test condition with both key & value, since I had same values but different keys but I required both entries. Since 'firstWhere' was ignoring the duplicate. Thanks – Ant D Aug 24 '20 at 06:03
  • 1
    Glad my answer helped you. MapEntry really help to visualize the structure of data, which can be very useful for debugging and testing. – Makdir Oct 30 '20 at 09:54
  • Thanks! Worked for me! This answer should have more upvote! – Al Mamun Mar 12 '22 at 02:30
6
Map map = {1: 'one', 2: 'two', 3: 'three'};

var key = map.keys.firstWhere((k) => map[k] == 'two', orElse: () => null);
print(key);
Matt Ke
  • 3,599
  • 12
  • 30
  • 49
Frank Gue
  • 141
  • 2
  • 3
  • While this code may help with the question, it is better to include some context, explaining how it works and when to use it. Code-only answers tend to be less useful in the long run. See [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) for some more info. – Klaus Gütter Jun 13 '20 at 15:52
  • in my case worked: map.entries.firstWhere((element) => element.value == 'two', orElse: () => null).key; – SardorbekR Feb 03 '21 at 11:24
2

You can do the following :

var mapper = { 
              '01' : 'USD',
               '17' : 'GBP'     } 

for(var val in mapper.keys){

  switch(mapper[val]){

        case 'USD' : {
                             print('key for ${mapper[val]} is : ' '${val}');  
            }

          break;

        case 'GBP' : {
                             print('key for ${mapper[val]} is : ' '${val}');   
               } 

        }
          }
2

If someone still need a solution, I wrote a simple library to deeply (search inside nested maps either) search by value inside Map. Usage is simple, because deepSearchByValue() is an extension method, so all you need to do is to import my library and call the method on your map:

import 'package:deep_collection/deep_collection.dart';


void main() {
  print({
    "01": "USD",
    "17": "GBP",
    "33": "EUR",
  }.deepSearchByValue((value) => value == 'USD'));
}

Owczar
  • 2,335
  • 1
  • 17
  • 24
1

Building on Randal Schwartz's answer:

Map<T, R> invertMap<T, R>(Map<R, T> toInvert) =>
  Map.fromEntries(toInvert.entries.map((e) => MapEntry(e.value, e.key)));
1

An extension of Randal Schwartz's answer.

extension InvertMap<K, V> on Map<K, V> {
  Map<V, K> get inverse => Map.fromEntries(entries.map((e) => MapEntry(e.value, e.key)));
}

This provides us with a highly reusable solution:

var inverseMap = originalMap.inverse;
Jani
  • 197
  • 15