Sum of all values in a map in Dart - dart

I have a Map<String, Map<String, double>> myMap = ... and I would like to sum all the values in the second map. I have managed to do it like this
double sum = 0;
myMap.entries.forEach((element) {
Map<String, double> map = element.value;
sum += map.entries.map((e) => e.value).toList().fold(0, (a, b) => a + b);
});
Is it possible to sum it using only one line without .forEach()?

ok, then an another option:
var sum = myMap.values.expand((e) => e.values).fold(0, (a, b) => a + b);

Try this one liner:
num sum = 0;
map.forEach((k, v) => v.forEach((kk, vv) => sum += vv));

I've managed to come up with the solution that works and all in one line.
double sum = myMap.values
.map((e) => e.values)
.fold(0, (a, b) => a + b.fold(0, (a, b) => a + b));

Related

How to fill a List with entries from a Map in Dart

I want to do the equivalent of this Python code in Dart. Possibly as a one liner I could use in a return statement.
m = {1: 'a', 2: 'b', 3: 'c'}
l = [1, 3]
[m[index] for index in l]
this results in a new list like this ['a', 'c']
A long version of this in Dart would be this.
List<String> r = [];
for (var key in l) {
r.add(m[key]);
}
I think this is what you are asking for:
void main() {
final m = {1: 'a', 2: 'b', 3: 'c'};
final l = [1, 3, 4];
List<String> r1 = m.entries.where((e) => l.contains(e.key)).map((e) => e.value).toList();
List<String> r2 = l.where((k) => m.containsKey(k)).map((k) => m[k]).toList();
print(r1); // [a, c]
print(r2); // [a, c]
}
Update 1: Added another example (r2) which iterate over the list instead.
Update 2: Added check to second solution so it only map keys there are in the map.

Performance testing in dart using test 0.12.15+3 lib

We develop a computationally-intensive web app in Dart.
For the purposes of making sure our computations perform well across all platforms and browsers, we run benchmarks using the "test 0.12.15+3" package. However, we found out that in some cases, the difference in executing the same code differs by orders of magnitude. Below is the code that demonstrates the problem (sorting arrays using custom comparators).
I wonder if there is an explanation for the difference in time between the code being executed in chrome, and as test with choice of chrome as platform (pub run test -p chrome test/perf_test.dart) ?
Is benchmarking via the test package a viable option, or should we look elsewhere?
import 'package:quiver/iterables.dart' as it;
void main(){
Stopwatch sw = new Stopwatch();
int len = 1000000;//0000
num v = 0;
List ln0 = new List();
for(int i = 0; i < len; i++)
ln0.add(v++);
//T1
sw..reset()..start();
ln0.sort((x,y) => x - y);
sw..stop();
print('Num Comparator take, mcs: ${sw.elapsedMicroseconds}');
//T2
List ln1= it.range(len).toList();
sw..reset()..start();
ln1.sort((x,y) => x - y);
print('Suddenly, Num Comparator take, mcs: ${sw.elapsedMicroseconds}');
//T3
List li2 = it.range(len).map((numm)=>numm.toInt()).toList();
sw..reset()..start();
li2.sort((x,y)=>x - y);
sw..stop();
print('Int Comparator take, mcs: ${sw.elapsedMicroseconds}');
List<String> items = new List(len);
for(int i =0, len = items.length; i<len; i++){
List tl = ['a','b','c','d','e','f','g','h','i','j','']..shuffle();
items[i] = tl.join('');
}
Function _comparer = (String s1, String s2) {
if (s1 == null && s2 == null) return 0;
if (s1 == null) return 1;
if (s2 == null) return -1;
if (s1 == '' && s2 == '') return 0;
if (s1 == '') return 1;
if (s2 == '') return -1;
return s1.compareTo(s2);
};
//T4
List ls1 = new List.from(items);
sw..reset()..start();
ls1.sort((s1, s2) => s1.compareTo(s2));
sw..stop();
print('Standart String comparator take, mcs: ${sw.elapsedMicroseconds}');
//T5
List ls2 = new List.from(items);
sw..reset()..start();
ls2.sort(_comparer);
sw..stop();
print('String comparator(miss null,empty) take, mcs: ${sw.elapsedMicroseconds}');
}
test is not supposed to be used for benchmarks. Use insted https://pub.dartlang.org/packages/benchmark_harness. It helps to cope with benchmark related requirements like warmup phase and number of runs to get more realistic results.

Ruby/Rails while loop not breaking correctly?

I am working on a client's site, and I'm writing an amortization schedule calculator in in ruby on rails. For longer loan term calculations, it doesn't seem to be breaking when the balance reaches 0
Here is my code:
def calculate_amortization_results
p = params[:price].to_i
i = params[:rate].to_d
l = params[:term].to_i
j = i/(12*100)
n = l * 12
m = p * (j / (1 - (1 + j) ** (-1 * n)))
#loanAmount = p
#rateAmount = i
#monthlyAmount = m
#amort = []
#interestAmount = 0
while p > 0
line = Hash.new
h = p*j
c = m-h
p = p-c
line["interest"] = h
line["principal"] = c
if p <= 0
line["balance"] = 0
else
line["balance"] = p
end
line["payment"] = h+c
#amort.push(line)
#interestAmount += h
end
end
And here is the view:
- #amort.each_with_index do |a, i|
%li
.m
= i+1
.i
= number_to_currency(a["interest"], :unit => "$")
.p
= number_to_currency(a["principal"], :unit => "$")
.pp
= number_to_currency(a["payment"], :unit => "$")
.b
= number_to_currency(a["balance"], :unit => "$")
What I am seeing is, in place of $0.00 in the final payment balance, it shows "-$-inf", iterates one more loop, then displays $0.00, but shows "-$-inf" for interest. It should loop until p gets to 0, then stop and set the balance as 0, but it isn't. Any idea what I've done wrong?
The calculator is here. It seems to work fine for shorter terms, like 5 years, but longer terms cause the above error.
Edit:
Changing the while loop to n.times do
and then changing the balance view to
= number_to_currency(a["balance"], :unit => "$", :negative_format => "$0.00")
Is a workaround, but i'd like to know why the while loop wouldn't work correctly
in Ruby the default for numerical values is Fixnum ... e.g.:
> 15 / 4
=> 3
You will see weird rounding errors if you try to use Fixnum values and divide them.
To make sure that you use Floats, at least one of the numbers in the calculation needs to be a Float
> 15.0 / 4
=> 3.75
> 15 / 4.0
=> 3.75
You do two comparisons against 0 , which should be OK if you make sure that p is a Float.
As the other answer suggests, you should use "decimal" type in your database to represent currency.
Please try if this will work:
def calculate_amortization_results
p = params[:price].to_f # instead of to_i
i = params[:rate].to_f # <-- what is to_d ? use to_f
l = params[:term].to_i
j = i/(12*100.0) # instead of 100
n = l * 12
m = p * (j / (1 - (1 + j) ** (-1 * n))) # division by zero if i==0 ==> j==0
#loanAmount = p
#rateAmount = i
#monthlyAmount = m
#amort = []
#interestAmount = 0.0 # instead of 0
while p > 0
line = Hash.new
h = p*j
c = m-h
p = p-c
line["interest"] = h
line["principal"] = c
if p <= 0
line["balance"] = 0
else
line["balance"] = p
end
line["payment"] = h+c
#amort.push(line)
#interestAmount += h
end
end
If you see "inf" in your output, you are doing a division by zero somewhere.. better check the logic of your calculation, and guard against division by zero.
according to Wikipedia the formula is:
http://en.wikipedia.org/wiki/Amortization_calculator
to improve rounding errors, it's probably better to re-structure the formula like this:
m = (p * j) / (1 - (1 + j) ** (-1 * n) # these are two divisions! x**-1 == 1/x
which is equal to:
m = (p * j) + (p * j) / ((1 + j) ** n) - 1.0)
which is equal to: (use this one)
q = p * j # this is much larger than 1 , so fewer rounding errors when dividing it by something
m = q + q / ((1 + j) ** n) - 1.0) # only one division
I think it has something to do with the floating point operations precision. It has already been discussed here: Ruby number precision with simple arithmetic and it would be better to use decimal format for financial purposes.
The answer could be computing the numbers in the loop, but with precomputed number of iterations and from the scratch.

Using F# Indexed Properties in a Type

I'm trying to convert the following C# into F#:
public class Matrix
{
double[,] matrix;
public int Cols
{
get
{
return this.matrix.GetUpperBound(1) + 1;
}
}
public int Rows
{
get
{
return this.matrix.GetUpperBound(0) + 1;
}
}
public Matrix(double[,] sourceMatrix)
{
this.matrix = new double[sourceMatrix.GetUpperBound(0) + 1, sourceMatrix.GetUpperBound(1) + 1];
for (int r = 0; r < this.Rows; r++)
{
for (int c = 0; c < this.Cols; c++)
{
this[r, c] = sourceMatrix[r, c];
}
}
}
public double this[int row, int col]
{
get
{
return this.matrix[row, col];
}
set
{
this.matrix[row, col] = value;
}
}
}
This is what I have so far:
type Matrix(sourceMatrix:double[,]) =
let mutable (matrix:double[,]) = Array2D.create (sourceMatrix.GetUpperBound(0) + 1) (sourceMatrix.GetUpperBound(1) + 1) 0.0
member this.Item
with get(x, y) = matrix.[(x, y)]
and set(x, y) value = matrix.[(x, y)] <- value
do
for i = 0 to matrix.[i].Length - 1 do
for j = (i + 1) to matrix.[j].Length - 1 do
this.[i].[j] = matrix.[i].[j]
My type above seems to have two problems I'm not sure how to resolve. The first one is that matrix.[(x, y)] is expected to have type `a[] but has type double[,]. The second is type definitions must have let/do bindings preceding member and interface definitions. The problem with that is I'm trying to populate an indexed property in the do block, which means I have to create it first.
Thanks in advance,
Bob
Regarding your first problem, you want to use matrix.[x,y] instead of matrix.[(x,y)] - your matrix is indexed by two integers, not by a tuple of integers (although these are conceptually similar).
Here's something roughly equivalent to your C#:
type Matrix(sourceMatrix:double[,]) =
let rows = sourceMatrix.GetUpperBound(0) + 1
let cols = sourceMatrix.GetUpperBound(1) + 1
let matrix = Array2D.zeroCreate<double> rows cols
do
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
matrix.[i,j] <- sourceMatrix.[i,j]
member this.Rows = rows
member this.Cols = cols
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value = matrix.[x, y] <- value
This assumes that your matrix can't actually be reassigned (e.g. in the C# you've posted, you could have made your matrix field readonly - unless there's additional code that you've hidden). Therefore, the number of rows and columns can be calculated once in the constructor since the entries of the matrix may change but its size won't.
However, if you want a more literal translation of your code, you can give your newly constructed instance a name (this in this case):
type Matrix(sourceMatrix:double[,]) as this =
let mutable matrix = Array2D.zeroCreate<double> (sourceMatrix.GetUpperBound(0) + 1) (sourceMatrix.GetUpperBound(1) + 1)
do
for i in 0 .. this.Rows - 1 do
for j in 0 .. this.Cols - 1 do
this.[i,j] <- sourceMatrix.[i,j]
member this.Rows = matrix.GetUpperBound(0) + 1
member this.Cols = matrix.GetUpperBound(1) + 1
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value = matrix.[x, y] <- value
type Matrix(sourceMatrix:double[,]) =
let matrix = Array2D.copy sourceMatrix
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value = matrix.[x, y] <- value

Different behaviour between Join and SelectMany after replacing one of the sets

I hope that someone can shed a light on the (to me) unexpected behavioral difference between the two (result wise) equal queries.
A small program can be worth a thousand words, so here goes :
static void Main(string[] args)
{
var l1 = new List<int> { 1, 2, 3 };
var l2 = new List<int> { 2, 3, 4 };
var q1 = // or var q1 = l1.Join(l2, i => i, j => j, (i, j) => i);
from i in l1
join j in l2
on i equals j
select i;
var q2 = //or var q2 = l1.SelectMany(i => l2.Where(j => i == j));
from i in l1
from j in l2
where i == j
select i;
var a1 = q1.ToList(); // 2 and 3, as expected
var a2 = q2.ToList(); // 2 and 3, as expected
l2.Remove(2);
var b1 = q1.ToList(); // only 3, as expected
var b2 = q2.ToList(); // only 3, as expected
// now here goes, lets replace l2 alltogether.
// Afterwards, I expected the same result as q1 delivered...
l2 = new List<int> { 2, 3, 4 };
var c1 = q1.ToList(); // only 3 ? Still using the previous reference to l2 ?
var c2 = q2.ToList(); // 2 and 3, as expected
}
Now I know that Join internally uses a lookup class to optimize performance, and without too much knowledge, my guess is that the combination of that with captured variables might cause this behavior, but to say I really understand it, no :-)
Is this an example of what Joel calls "a leaky abstraction" ?
Cheers,
Bart
You're actually nearly there, given your query expansions in the comments:
var q1 = l1.Join(l2, i => i, j => j, (i, j) => i);
var q2 = l1.SelectMany(i => l2.Where(j => i == j));
Look at where l2 is used in each case. In the Join case, the value of l2 is passed into the method immediately. (Remember that the value is a reference to the list though... changing the contents of the list isn't the same as changing the value of l2.) Changing the value of l2 later doesn't affect what the query returned by the Join method remembers.
Now look at SelectManay: l2 is only used in the lambda expression... so it's a captured variable. That means that whenever the lambda expression is evaluated, the value of l2 at that moment in time is used... so it will reflect any changes to the value.

Resources