Assume that I am calling an API endpoint and getting back some exchange rates in the form of a DataTable. I then filter those exchange rates using a LINQ statement to return only those rates I am interested in.
LINQ for filtering exchange rates:
var results = exchangeRates.Rows.Cast<DataRow>()
.Where(r => r.Field<double>("Rate") > 0)
.Where(r => r.Field<string>("FromCurrency").ToUpper() == "USD")
.Select(y => new
{
FromCurrency = y.Field<string>("FromCurrency"),
ToCurrency = y.Field<string>("ToCurrency"),
ExchangeRate = y.Field<double>("Rate")
}).ToList();
LINQ statement returns:
+------------------+----------------+---------+
| OriginalCurrency | TargetCurrency | Rate |
+------------------+----------------+---------+
| USD | GBP | 88.452 |
+------------------+----------------+---------+
| USD | CAD | 132.819 |
+------------------+----------------+---------+
I would like to add, to the resultant records, the reciprocal exchange rates. So if I have an exchange rate of USD to GBP of 88.45 I would like to add a record for GBP to USD of 113.06. So basically I swap the OriginalCurrency and TargetCurrency columns and take the reciprocal of the first rate and then multiply by 10,000. I have the LINQ to filter the records but cannot figure out how to adjust the LINQ statement to add the two new reciprocal exchange rate records.
Desired LINQ statement return:
+------------------+----------------+--------+
| OriginalCurrency | TargetCurrency | Rate |
+------------------+----------------+--------+
| USD | GBP | 88.45 |
+------------------+----------------+--------+
| USD | CAD | 132.81 |
+------------------+----------------+--------+
| GBP | USD | 113.06 |
+------------------+----------------+--------+
| CAD | USD | 75.30 |
+------------------+----------------+--------+
You can Select
the reciprocal exchange rates into new enumerable first
var reciprocalResults = results
.Select(y => new
{
FromCurrency = y.ToCurrency,
ToCurrency = y.FromCurrency ,
ExchangeRate = Math.Round (10000 / y.ExchangeRate, 2)
});
Then Concat
both results into new list
var total = results.Concat(reciprocalResults).ToList();
Since you want to map each item in the sequence into 2 items (the rate and the reciprocal), you should use SelectMany
.
First, write a method that, given a row in the table, returns 2 rows:
// Create a class called ExchangeRate, with the three properties in your anonymous object
private static IEnumerable<ExchangeRate> RateAndReciprocal(ExchangeRate rate) {
yield return rate;
yield return new ExchangeRate {
FromCurrency = rate.ToCurrency,
ToCurrency = rate.FromCurrency,
ExchangeRate = 10000 / rate.ExchangeRate
};
}
Then, call SelectMany
at the end of the method chain:
.Select(y => new ExchangeRate
{
FromCurrency = y.Field<string>("FromCurrency"),
ToCurrency = y.Field<string>("ToCurrency"),
ExchangeRate = y.Field<double>("Rate")
})
.SelectMany(RateAndReciprocal)
.ToList();
(Of course, you could have made RateAndReciprocal
inline, which would have saved you from creating the ExchangeRate
class, but I like this better)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.