Reputation: 19415
I have a Bank
class
which contains exchange rates
. I can add items into the map but cannot retrieve the value with the same key I used to put inside the map.
class Bank {
Map<Map<String, String>, double> _exchangeRates = Map();
void addExchangeRate(String from, String to, double i) {
_exchangeRates[{from: to}] = i;
}
double getExchangeRate(String from, String to) {
return _exchangeRates[{from, to}];
}
}
void main(){
Bank bank = Bank();
bank.addExchangeRate("USD", "CHF", 2);
bank.addExchangeRate("INR", "USD", 1 / 60);
bank.addExchangeRate("INR", "NRS", 160/100);
print(bank.getExchangeRate("USD","CHF"));
print(bank.getExchangeRate("INR","USD"));
print(bank.getExchangeRate("INR","NRS"));
}
Output :
null
null
null
Upvotes: 2
Views: 1179
Reputation: 71813
As a third option, I'll suggest using a Map
with a non-standard equality. That is one of the uses that the MapEquality
from package collection
is intended for.
import 'package:collection/collection.dart';
class Bank {
static const _me = MapEquality();
Map<Map<String, String>, double> _exchangeRates =
Map(equals: _me.equals, hashCode: _me.hash);
void addExchangeRate(String from, String to, double i) {
_exchangeRates[{from: to}] = i;
}
double getExchangeRate(String from, String to) =>
_exchangeRates[{from: to}];
}
void main() {
Bank bank = Bank();
bank.addExchangeRate('USD', 'CHF', 2);
bank.addExchangeRate('INR', 'USD', 1 / 60);
bank.addExchangeRate('INR', 'NRS', 160 / 100);
print(bank.getExchangeRate('USD', 'CHF'));
print(bank.getExchangeRate('INR', 'USD'));
print(bank.getExchangeRate('INR', 'NRS'));
}
This makes the lookup more efficient because it does hash-based lookup instead of linear search. There is still the overhead of creating a new map for each lookup.
It seems the "map" here is really just a pair. A Map
is a high-cost abstraction for storing just a single pair, and it doesn't have a natural equality. The suggestion of using "$from$to"
as key is better than using a key. If you need to separate the values later, you could also use a new class containing the two strings, and with an equals and hash code to match, like:
class _StringPair {
final String first;
final String second;
_StringPair(this.first, this.second);
int get hashCode => (first.hashCode * 37 + second.hashCode * 17) & 0x3FFFFFFF;
bool operator==(Object other) =>
other is _StringPair && first == other.first && second == other.second;
}
Then use StringPair(from,to)
that as keys instead of {from: to}
.
Upvotes: 2
Reputation: 6886
The problem is, in Dart
everything is an object and the Map
you are seeking for is not same Object
the Map
you are searching with. So you are getting null. You need advanced methods for this.
This is the solution:
import 'package:collection/collection.dart';
class Bank {
Function equals = const MapEquality().equals;
Map<Map<String, String>, double> _exchangeRates = Map();
void addExchangeRate(String from, String to, double i) {
_exchangeRates[{from: to}] = i;
}
double getExchangeRate(String from, String to) {
return _exchangeRates[_exchangeRates.keys.firstWhere((entry){
return equals(entry, {from : to});
})];
}
}
void main() {
Bank bank = Bank();
bank.addExchangeRate('USD', 'CHF', 2);
bank.addExchangeRate('INR', 'USD', 1 / 60);
bank.addExchangeRate('INR', 'NRS', 160 / 100);
print(bank.getExchangeRate('USD', 'CHF'));
print(bank.getExchangeRate('INR', 'USD'));
print(bank.getExchangeRate('INR', 'NRS'));
}
Upvotes: 2
Reputation: 103541
That's because you are using objects as Keys, but when you try to retrieve the values you are creating new objects, so the result value is null.
I would use String
as a Key composed by from
and to
values, like this:
class Bank {
Map<String, double> _exchangeRates = Map();
void addExchangeRate(String from, String to, double i) {
_exchangeRates["$from$to"] = i;
}
double getExchangeRate(String from, String to) {
return _exchangeRates["$from$to"];
}
}
void main() {
Bank bank = Bank();
bank.addExchangeRate("USD", "CHF", 2);
bank.addExchangeRate("INR", "USD", 1 / 60);
bank.addExchangeRate("INR", "NRS", 160/100);
print(bank.getExchangeRate("USD","CHF"));
print(bank.getExchangeRate("INR","USD"));
print(bank.getExchangeRate("INR","NRS"));
}
Upvotes: 4