why dart Map returns null? - flutter

I'm trying to sum Map values. but i am getting error. I think it's because Map returns null. I will be glad if you help.
I try that code;
void main() {
List t = ['tag1', 'tag2'];
List f = ['1', '2', '3'];
List data = [
['1', 0.5, 0.6],
['2', 0.7, 0.8],
['3', 0.9, 1]
];
Map answers = {};
for (final i in data) {
answers[i[0]] = i.skip(1);
}
var qSum = 0.0;
for (int tg = 0; tg < t.length; tg++) {
for (final i in f) {
var val = answers[i][tg];
qSum = qSum + (val);
}
}
}

It's because skip returns an Iterable and not a List. Change
answers[i[0]] = i.skip(1);
to
answers[i[0]] = i.skip(1).toList();

Related

split the string into equal parts flutter

There is a string with random numbers and letters. I need to divide this string into 5 parts. And get List. How to do it? Thanks.
String str = '05b37ffe4973959c4d4f2d5ca0c1435749f8cc66';
Should work:
List<String> list = [
'05b37ffe',
'4973959c',
'4d4f2d5c',
'a0c14357',
'49f8cc66',
];
I know there'a already a working answer but I had already started this so here's a different solution.
String str = '05b37ffe4973959c4d4f2d5ca0c1435749f8cc66';
List<String> list = [];
final divisionIndex = str.length ~/ 5;
for (int i = 0; i < str.length; i++) {
if (i % divisionIndex == 0) {
final tempString = str.substring(i, i + divisionIndex);
list.add(tempString);
}
}
log(list.toString()); // [05b37ffe, 4973959c, 4d4f2d5c, a0c14357, 49f8cc66]
String str = '05b37ffe4973959c4d4f2d5ca0c1435749f8cc66';
int d=1
; try{
d = (str.length/5).toInt();
print(d);
}catch(e){
d=1;
}
List datas=[];
for(int i=0;i<d;i++){
var c=i+1;
try {
datas.add(str.substring(i * d, d*c));
} catch (e) {
print(e);
}
}
print(datas);
}
OR
String str = '05b37ffe4973959c4d4f2d5ca0c1435749f8cc66';
int d = (str.length / 5).toInt();
var data = List.generate(d - 3, (i) => (d * (i + 1)) <= str.length ? str.substring(i * d, d * (i + 1)) : "");
print(data);//[05b37ffe, 4973959c, 4d4f2d5c, a0c14357, 49f8cc66]
If you're into one liners, with dynamic parts.
Make sure to import dart:math for min function.
This is modular, i.e. you can pass whichever number of parts you want (default 5). If you string is 3 char long, and you want 5 parts, then it'll return 3 parts with 1 char in each.
List<String> splitIntoEqualParts(String str, [int parts = 5]) {
int _parts = min(str.length, parts);
int _sublength = (str.length / _parts).ceil();
return Iterable<int>
//Initialize empty list
.generate(_parts)
.toList()
// Apply the access logic
.map((index) => str.substring(_sublength * index, min(_sublength * index + _sublength, str.length)))
.toList();
}
You can then use it such as print(splitIntoEqualParts('05b37ffe4973959c4d4f2d5ca0c1435749f8cc66', 5));
splitWithCount(String string,int splitCount)
{
var array = [];
for(var i =0 ;i<=(string.length-splitCount);i+=splitCount)
{
var start = i;
var temp = string.substring(start,start+splitCount);
array.add(temp);
}
print(array);
}

Making a copy/clone of a "List<List<Map>>"

I'm trying to create a copy/clone of a "List<List<Map'>>".
So far I tried:
dataFTY2 = dataFTY.map((element)=>element).toList();
dataFTY2 = json.decode(json.encode(dataFTY));
dataFTY2 = List.from(dataFTY);
Nothing seems to work. Whenever I change the copy "dataFTY2", dataFTY changes as well. I need this to be a completely independent copy. Please help. I cant seem to figure this out, its driving me crazy.
More code added for reference.
List failureDetails = [];
List trackIDs = [];
List dateTime = [];
var dataFTY2 = dataFTY.map((element) => element.map((ele) => Map.from(ele)).toList()).toList();
// get historyData for each one and sort through "F"s and put them into the table in a row?
for (var x in dataFTY2[4]) {
trackIDs.add(x["track_id"]);
dateTime.add(x["datetime"]);
}
List failuresOnly = List.filled(trackIDs.length, {}, growable: true);
for (var i = 0; i < trackIDs.length; i++) {
await fetchTrackIDTestDetails(context, trackIDs[i], dateTime[i], false);
failureDetails.add(MyGlobals().getTestCodeDetailsData());
}
//filter out only "F"s
for (var p = 0; p < failureDetails.length; p++) {
for (var t in failureDetails[p][0]) {
if (t["Status"] == "F") {
//add it to list, if pass do nothing
failuresOnly[p] = t;
}
}
}
//combine with FTY failure data, don't use new screen use old screen and toggle when pressed, add column on right side
//dataFTY2 = MyGlobals().getFTYFailureMoreDetails();
for (var i = 0; i < dataFTY2[4].length; i++) {
dataFTY2[4][i]["TestCode"] = failuresOnly[i]["TestCode"];
dataFTY2[4][i]["Status"] = failuresOnly[i]["Status"];
dataFTY2[4][i]["TestValue"] = failuresOnly[i]["TestValue"];
dataFTY2[4][i]["Lo_Limit"] = failuresOnly[i]["Lo_Limit"];
dataFTY2[4][i]["Up_Limit"] = failuresOnly[i]["Up_Limit"];
dataFTY2[4][i]["ProcTime"] = failuresOnly[i]["ProcTime"];
}
You can use Map.from named constructor to clone the Map like this,
dataFTY2 = dataFTY.map((element) => element.map((ele) => Map.from(ele)).toList()).toList();
I find it more straightforward to use collection-for and the spread (...) operator:
void main() {
var original = [
[
{'foo': 1, 'bar': 2},
{'foo': 3, 'bar': 4},
]
];
// Create a new List...
var copy = [
for (var sublist in original)
// ... where each element is a new List...
[
for (var map in sublist)
// ... where each element of the sublist is a new Map that
// copies all entries from `map`.
{...map},
],
];
original[0][0]['foo'] = -1;
print(original); // Prints: [[{foo: -1, bar: 2}, {foo: 3, bar: 4}]]
print(copy); // Prints: [[{foo: 1, bar: 2}, {foo: 3, bar: 4}]]
}

Mapping Lists from 2 lists flutter

sample of Options that i have:
I have 2 List, the first one is named options:
List<String> _options = [
'Arts & entertainment',
'Biographies & memoirs',
...
];
and the other name _isOptionSelected:
List<bool> _isOptionSelected = [
false,
false,
..
];
im trying to generat a map form those 2 list.
what i have tryed is this:
Map<String, Map<String, dynamic>> _isOptionMap = {
'Arts & entertainment': {
'optionName': 'Arts & entertainment',
'isOptionSelected': false,
},
'Biographies & memoirs': {
'optionName': 'Biographies & memoirs',
'isOptionSelected': false,
},
..
};
and then print it:
for (int i = 0; i < _isChoiceChipSelected.length; i++) {
_isOptionMap[_options[i]]['isOptionSelected'].update(
_options[i],
(value) => _isOptionMap[_options[i]]
['isOptionSelected']);
}
print(_isOptionMap);
Is a logical problem? and what im I doing wong ?
Hello this code creates a map like the one you want.
Be aware that "_options" and "_isOptionSelected" lists must have the same lenght.
void main() {
List<String> _options = [
'Arts & entertainment',
'Biographies & memoirs',
];
List<bool> _isOptionSelected = [
false,
false,
];
Map m = {};
_options.asMap().entries.forEach((entry) {
int idx = entry.key;
String val = entry.value;
Map m1 = {
'optionName': val,
'isOptionSelected': _isOptionSelected[idx]
};
m[val] = m1;
});
print( m );
}

Dart sum list of lists by element

I'm trying to add all elements in a list of lists by index and average them:
List<List<double>> data = [[1.0, 2.0, 3.0], [2.0, 3.0, 5.0], [8.0, 7.0, 2.0]]
The result should be a list of doubles each summed up and then divided by the total lengths of above data:
[11.0, 12.0, 10.0] // divide these by 3
[3.67, 4.0, 3.33] // should be the result
What is the best way to do this? This is taking too long in my flutter app (actual data list contains 60 lists of 2000 doubles each) and yes, I am also asserting the length of each list is equal. and is not empty or having unexpected data types.
Well I really don't know about the speed you need.
Try this method to see if it works for your dataset. Maybe your method is faster!
void main() {
List<List<double>> data = [[1.0, 2.0, 3.0], [2.0, 3.0, 5.0], [8.0, 7.0, 2.0]];
List<double> dataSum = List<double>();
// original data
print(data);
for (var item in data){
dataSum.add(item.fold(0, (p, c) => p + c) / item.length);
}
// output
print(dataSum);
}
Important:
Anyways, if you do a large task in time, you can use a async function with a Future to prevent the application to hang and not suffer because of the long wait.
UPDATE: After OP's comment
This code should give you the result you are expecting.
void main() {
List<List<double>> data = [[1.0, 2.0, 3.0], [2.0, 3.0, 5.0], [8.0, 7.0, 2.0]];
int numLists = data.length;
int numElements = data[0].length;
double sum;
List<double> dataSum = List<double>();
for(var i = 0; i < numElements; i++ ) {
sum = 0.0;
for(var j = 0; j < numLists; j++ ) {
sum += data[j][i]; //inverted indexes
}
dataSum.add(sum/numLists);
}
// output
print(dataSum);
}
My contribution for a Matrix NxM, I've modified your data for a more generic solution:
extension chesu<T> on List<List<T>> {
List<List<T>> transpose() {
final rowNum = this.length;
final colNum = this[0].length;
var list = List<List<T>>.generate(colNum, (i) => List<T>());
if (rowNum == 0 || colNum == 0) return null;
for (var r = 0; r < rowNum; r++)
for (var c = 0; c < colNum; c++) list[c].add(this[r][c]);
return list;
}
}
main(List<String> args) {
final data = [[1.0, 2.0, 3.0, 4.0], [2.0, 3.0, 5.0, 8.0], [6.0, 7.0, 7.0, 9.0]];
print(data.transpose().map((e) => e.reduce((v, e) => v+e)).map((e) => e/3));
}
Result:
(3.0, 4.0, 5.0, 7.0)
There is a new package named scidart that contains interesting functions like transpose, it tries to emulate numpy from Python.
UPDATE 1: Working with Big Data
UPDATE 2: I made a fool mistake with sum(), extension is fixed now, sorry.
import 'dart:math';
extension on List<List<double>> {
List<List<double>> transpose() {
final rowNum = this.length;
final colNum = this[0].length;
var list = List<List<double>>.generate(colNum, (i) => List<double>());
if (rowNum == 0 || colNum == 0) return null;
for (var r = 0; r < rowNum; r++)
for (var c = 0; c < colNum; c++) list[c].add(this[r][c]);
return list;
}
List<double> sum() => this.map((l) => l.reduce((v, e) => v+e)).toList();
}
class Stats {
List<List<double>> _data;
int _rows, _cols;
List<double> _sum, _avg;
Stats(List<List<double>> data) {
_data = data.transpose();
_rows = _data.length;
_cols = _data[0].length;
}
int get rows => _rows;
int get cols => _cols;
List<double> get sum {
if ([0, null].contains(_sum)) _sum = _data.sum();
return _sum;
}
List<double> get avg {
if ([0, null].contains(_avg)) _avg = sum.map((e) => e / _cols).toList();
return _avg;
}
}
main(List<String> args) {
// final data = [[1.0, 2.0, 3.0, 4.0], [2.0, 3.0, 5.0, 8.0], [6.0, 7.0, 7.0, 9.0]];
// final data = [[1.0, 2.0, 3.0], [2.0, 3.0, 5.0], [8.0, 7.0, 2.0]];
final data = List<List<double>>.generate(60, (i) => List<double>.generate(2000, (j) => Random().nextDouble()*30));
print('Creating big data...');
final stats = Stats(data);
final stopwatch = Stopwatch()..start();
print('Calculating statistics...');
print('Sum: ${stats.sum.take(5)}');
print('Average: ${stats.avg.take(5)}');
stopwatch.stop();
print('\nJob finished at ${stopwatch.elapsedMilliseconds/1000} seconds.');
}
Result:
Creating big data...
Calculating statistics...
Sum: (928.8075263386316, 934.3418807027017, 815.2172548417801, 833.6855783984151, 828.1013228547513)
Average: (15.480125438977193, 15.572364678378362, 13.586954247363002, 13.894759639973586, 13.801688714245854)
Job finished at 0.024 seconds.
For operations on list you have to iterate over it's items (for, map, forEach ...etc) which would take time (depending on the list length) so I guess you have to do some benchmarking.
Try this
List<double> sum = [];
List<double> average = [];
sum = data.reduce((a, b) {
List<double> list = [];
for (int i = 0; i < b.length; i++) {
list.add(a[i] + b[i]);
}
return list;
});
average = sum.map((e) => e / 3).toList();
print(sum);
print(average);
Let me suggest more compact solution:
List<List<double>> data = [[1.0, 2.0, 3.0], [2.0, 3.0, 5.0], [8.0, 7.0, 2.0]]
var result = <double>[];
final innerListSize = data[0].length;
for (int i = 0; i < innerListSize; i++) {
result.add(data.map((e) => e[i]).average);
}

How to match loop a single character with multiple characters in a list and return bigger list dart?

I'm new in flutter and don't know much about dart, and i want ask about my problem.
This my example to graft each character * in listb loop foreach element in lista:
void main() {
var lista = ['1', '2', '3'];
var listb = ['a***' ,'b*','c'];
List<String> filter1 = [];
List<String> filter2 = [];
List<String> filter3 = [];
//
for (var value in listb) {
if (value.contains("*")) {
for (var aa in lista) {
filter1.add( value.replaceFirst('*', '$aa'));
}
}
}
listb.removeWhere((aaa) => aaa.contains('*'));
filter1 = List.from(filter1)..addAll(listb) ;
print('filter1' + '$filter1');
//
for (var value in filter1) {
if (value.contains("*")) {
for (var aa in lista) {
filter2.add( value.replaceFirst('*', '$aa'));
}
}
}
filter1.removeWhere((aaa) => aaa.contains('*'));
filter2 = List.from(filter2)..addAll(filter1) ;
print('filter2' + '$filter2');
//
for (var value in filter2) {
if (value.contains("*")) {
for (var aa in lista) {
filter3.add( value.replaceFirst('*', '$aa'));
}
}
}
filter2.removeWhere((aaa) => aaa.contains('*'));
filter3 = List.from(filter3)..addAll(filter2) ;
print('filter3' + '$filter3');
}
Result out put
filter1[a1**, a2**, a3**, b1, b2, b3, c]
filter2[a11*, a12*, a13*, a21*, a22*, a23*, a31*, a32*, a33*, b1, b2, b3, c]
filter3[a111, a112, a113, a121, a122, a123, a131, a132, a133, a211, a212, a213, a221, a222, a223, a231, a232, a233, a311, a312, a313, a321, a322, a323, a331, a332, a333, b1, b2, b3, c]
And it's very bad if character * to be replace in listb is : "a***********" :))
Is there a shotter way to escape one character need replace is a loop to have result filter3 at output? Thks U!
Darish's answer is a cool application of set theory, though I would argue that it is overkill. You can also achieve this with listB.expand and a recursive generator method:
void main() {
final listA = ['1', '2', '3'];
final listB = ['a***', 'b*', 'c'];
final output = listB.expand((term) => permutationGenerator(term, listA)).toList();
print(output);
}
Iterable<String> permutationGenerator(String input, List<String> replacements) sync* {
if (input.length == 0) {
// If the input is empty, there's nothing to generate
return;
}
if (input.length == 1) {
// If the input is one character, there's no suffix to append
if (input == '*') {
// Input is '*' so yield all the values in replacements
yield* replacements;
} else {
// Input isn't '*' so just yield it alone
yield input;
}
}
// Trim off and cache the first character
String firstChar = input[0];
// Recursively process all possible permutations of the input minus
// the first character
for (var suffix in permutationGenerator(input.substring(1), replacements)) {
if (firstChar == '*') {
// If the first character is '*', replace it with all values in
// replacements and append to it the suffix values calculated
// from the recursive
yield* replacements.map((c) => c + suffix);
} else {
// The first character isn't '*' so just yield it directly
yield firstChar + suffix;
}
}
}
This will output the following list (formatted):
[
a111,
a211,
a311,
a121,
a221,
a321,
a131,
a231,
a331,
a112,
a212,
a312,
a122,
a222,
a322,
a132,
a232,
a332,
a113,
a213,
a313,
a123,
a223,
a323,
a133,
a233,
a333,
b1,
b2,
b3,
c,
]
You can create a general solution by taking Cartesian product of the input strings.
Step 1:
These are the input lists.
var lista = ['1', '2', '3'];
var listb = ['a***' ,'b*','c'];
Split each 'listb' item as shown below
listb.forEach((value) {
///split the string with asterisk symbol
var symbols = value.split('*');
}
Step 2:
For each asterisk symbol, calculate the Cartesian product of the input strings.
Iterable<List<String>> product = cartesian(
List<List<String>>.generate(symbols.length-1, (tempIndex) => lista));
product.forEach((productValue) {
///final output
print("$symbol${productValue.join()}");
});
The complete snippet is here.
void main() {
///strings that we should use for permutation
var lista = ['1', '2', '3'];
///input strings with asterisk that needs to be replaced.
var listb = ['a***', 'b*', 'c'];
listb.forEach((value) {
///split the string with asterisk symbol
var symbols = value.split('*');
for (int i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if (symbol.isNotEmpty) {
Iterable<List<String>> product = cartesian(
List<List<String>>.generate(symbols.length-1, (tempIndex) => lista));
product.forEach((productValue) {
///final output
print("$symbol${productValue.join()}");
});
}
}
});
}
Iterable<List<T>> cartesian<T>(List<List<T>> inputs) sync* {
if (inputs.isEmpty) {
yield List<T>(0);
return;
}
var indices = List<int>.filled(inputs.length, 0);
int cursor = inputs.length - 1;
outer:
do {
yield [for (int i = 0; i < indices.length; i++) inputs[i][indices[i]]];
do {
int next = indices[cursor] += 1;
if (next < inputs[cursor].length) {
cursor = inputs.length - 1;
break;
}
indices[cursor] = 0;
cursor--;
if (cursor < 0) break outer;
} while (true);
} while (true);
}
The output is
a111
a112
a113
a121
a122
a123
a131
a132
a133
a211
a212
a213
a221
a222
a223
a231
a232
a233
a311
a312
a313
a321
a322
a323
a331
a332
a333
b1
b2
b3
c
You can see a live demo here on DartPad.