In dart how add multiple list in a list? - flutter

I want to add multiple List in a List. The Length of the Outer loop is 2
and the length of the inner loop is 2.
List matchName = [];
List a = [];
List b = [];
void getMatchName(GetUserMatchModelRes m) {
matchName.clear();
for (var i = 0; i < m.ObjectList.length; i++) {
matchName.clear();
matchName.add(
m.ObjectList[i].ContactName,
);
print("i:$i");
for (var j = 0; j < m.ObjectList[i].ContactPhones.length; j++) {
print("j:$j");
matchName.add(
m.ObjectList[i].ContactPhones[j].MatchedContactName,
);
}
a.add(matchName);
print(a);
}
}
Output when outer loop is 0: [[a,b,c]]
When outer loop is 1: [[d,e,f],[d,e,f]]
But I want [[a,b,c],[d,e,f]]
How I can achieve this?

You're essentially doing:
var outer = <List<String>>[];
var inner = ['foo'];
outer.add(inner);
outer.add(inner);
Now outer has two elements that refer to the same object:
+---+---+
outer: | | |
+-|-+-|-+
| |
v v
+-------+
inner: | 'foo' |
+-------+
If you modify inner, you'll see the change in both outer[0] and in outer[1].
To avoid this, you need to add separate objects so that they can be modified independently. Either create new lists to add instead of modifying an existing one:
var outer = <List<String>>[];
outer.add(['foo']);
outer.add(['foo']);
or add copies:
var outer = <List<String>>[];
var inner = ['foo'];
outer.add([...inner]);
outer.add([...inner]);

Related

Is there a better way to calculate the moving sum of a list in flutter

Is there a better way to calculate a moving sum of a list?
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
int i = 0;
int maxLength = data.length - window + 1;
while (i < maxLength) {
List tmpData = data.getRange(i, i + window).toList();
double tmpSum = tmpData.reduce((a, b) => a + b);
sum.add(tmpSum);
i++;
}
// filling the first n values with null
i = 0;
while (i < window - 1) {
sum.insert(0, null);
i++;
}
return sum;
}
Well, the code is already clean for what you need. Maybe just some improvements like:
Use a for loop
You can use the method sublist which creates a "view" of a list, which is more efficient
To insert some values in the left/right of a list, there is a specific Dart method called padLeft, where you specify the lenght of the list which you want it to become (first parameter), then the value you want to use to fill it (second parameter). For example, if you have an array of N elements, and you want to fill it with X "null"s to the left, use padLeft(N+X, null).
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
for (int i = 0; i < data.length - window + 1; i++) {
List tmpData = data.sublist(i, i + window);
double tmpSum = tmpData.reduce((a, b) => a + b);
sum.add(tmpSum);
}
sum.padLeft(window - 1, null);
return sum;
}
if I understand your problem correctly you can just calculate the window one time and in one loop you can for each iteration you can add the current element to the sum and subtract i - (window - 1)
so for an input like this
data = [1,2,3,4,5,6]
window = 3
the below code will result in [6,9,12,15]
int sum = 0;
List<double> res = [];
for (int i = 0;i<data.length;i++) {
sum += data[i];
if (i < window - 1) {
continue;
}
res.add(sum);
sum -= data[i - (window - 1)]; // remove element that got out of the window size
}
this way you won't have to use getRange nor sublist nor reduce as all of those are expensive functions in terms of time and space complexity

AGGrid - Aggregation, Filtering

In agGrid, I have an aggregation which is based on two columns. When I apply filter, the aggregates based on two columns are not updated. There is no problem with sum, max, min aggregate functions as all these are based on same column.
here is the steps I follow,
Group by a Column --> Value Aggregation --> Weighted Avg(Custom Aggregation) --> Add a filter.
When I add a filter after weighted avg aggregation calculation, the new weighted avg is not refreshed.
I have this aggregate calculated using a valueGetter function (as in the code below).
Is there a way to update the aggregates which comes from a valueGetter function when I modify the filter?
Thanks in advance.
Regards,
Vijay.
function weightedAverageGetter(params) {
var col = params.column.colId.split('.')[1];
var value = 0;
if (params.data){
value = params.data.qli?params.data.qli[col]:0;
if (col == 'P1prime__c' || col == 'P2Prime__c'){
value = Math.ceil(value);
}
}
var avgW = 0;
if (params.node){
var sumVal = 0;
var sumQty = 0;
for (var node in params.node.allLeafChildren){
var nodeValue = params.node.allLeafChildren[node];
var val = 0;
var qty = 0;
if (nodeValue.data){
val = nodeValue.data.qli?nodeValue.data.qli[col]:0;
qty = nodeValue.data.qli?parseFloat(nodeValue.data.qli.Quantity):0;
}
if (typeof val !=='undefined' && val != '' && typeof qty !=='undefined' && qty != '') {
sumQty += qty;
sumVal += qty*val;
}
}
avgW = sumVal/sumQty;
}
avgW = Math.round(avgW * 100) / 100;
if(!params.column.aggregationActive || Number.isNaN(avgW)){
avgW = '';
}
return params.data?value:avgW;
}

How to exclude a column when using getAllColumns property in ag-grid

I have a function that counts and hides the number of columns that does not fit the screen. I want to exclude a column when resizing and hiding the columns. Here is what I have.
let ctrOfColumns = this.gridOptionsValue.columnApi.getAllColumns();
this returns the columns that i have. I want to exclude a specific column which has a colId of 'toBeExcludedId' so that It won't be included in the hiding of columns algo.
Here is my algo in hiding of the columns
let gridWidthOfMyTable = $('#idOfMyGrid').outerWidth();
let columnsToBeShown = [];
let columnsToBeHidden = [];
let totalWidthOfColumn = 0;
for(let x = 0 ; x < ctrOfColumns.length; x ++){
const singleColumn = ctrOfColumns[x];
totalWidthOfColumn += singleColumn.getMinWidth();
if (totalWidthOfColumn > gridWidthOfMyTable) {
columnsToBeHidden.push(singleColumn);
} else {
columnsToBeShown.push(singleColumn);
}
}
this.gridOptionsValue.columnApi.setColumnsVisible(columnsToBeShown, true);
this.gridOptionsValue.columnApi.setColumnsVisible(columnsToBeHidden, false);
There is no need to loop through all the values in your array. You can just use chaining and apply a filter directly to getAllColumns(), like this:
let ctrOfColumns = this.gridOptionsValue
.columnApi
.getAllColumns()
.filter((column) => column.colId !== 'toBeExcludedId');

How to refer variable in outter scope in coffeescript

All:
When I followed coffeescript tutorial on its official website, there is a sample:
outer = 1
changeNumbers = ->
inner = -1
outer = 10
inner = changeNumbers()
Equals:
var changeNumbers, inner, outer;
outer = 1;
changeNumbers = function() {
var inner;
inner = -1;
return outer = 10;
};
inner = changeNumbers();
I wonder how it looks like in coffeescript if I want to access inner in the outter scope from function changeNumber?
Define inner before changeNumber and coffeeScript won't see it as an inner variable. For example:
outer = 1
inner = 2
changeNumbers = ->
inner = -1
outer = 10
inner = changeNumbers()
Will compile into something like this:
var changeNumbers, inner, outer;
outer = 1;
inner = 2;
changeNumbers = function() {
inner = -1;
return outer = 10;
};
inner = changeNumbers();
As mentioned in the CoffeeScript documentation, when writing a deeply nested function, you need to be careful that you're not reusing the name of an external variable accidentally.

EF multiple aggregate in single query

I want to get count of a set based on different condition:
var invoices = new AccountingEntities().Transactions
var c1 = invoices.Count(i=>i.Type = 0);
var c2 = invoices.Count(i=>i.Type = 1);
var c3 = invoices.Count(i=>i.Type = 2);
How its possible to call all three queries in one DB round trip to increase performance?
Sure, just wrap up your three counts in a POCO or anonymous type:
using (var invoices = new AccountingEntities())
{
var c = (from i in invoices.Transactions
select new
{
c1 = invoices.Count(i=>i.Type = 0),
c2 = invoices.Count(i=>i.Type = 1),
c3 = invoices.Count(i=>i.Type = 2)
}).Single();
}
Also, dispose your context, as I show.
To aggregate arbitrary subqueries, use a dummy single-row result set from which you nest the desired subqueries. Assuming db represents your DbContext, the code to count invoice types will look like this:
var counts = (
from unused in db.Invoices
select new {
Count1 = db.Invoices.Count(i => i.Type == 0),
Count2 = db.Invoices.Count(i => i.Type == 1),
Count3 = db.Invoices.Count(i => i.Type == 2)
}).First();
If the want to generically get a count of all types, use grouping:
var counts =
from i in db.Invoices
group i by i.Type into g
select new { Type = g.Key, Count = g.Count() };