how to create multi dimension LIsts in dart Language? - dart

How to create Multidimensional List in dart?. IN other languages we can use array for this But in dart
we use List . SO i find in google I could not found method for Create Multidimensional List in dart ?
Anyone Know create Multidimensional List in dart ?

There are multiple ways to accomplish that. The simplest solution is to create a list of lists like:
void main() {
// Create 5x5 list
List<List<int>> twoDimList = List.generate(5, (_) => List.filled(5, 0));
twoDimList[0][0] = 5;
print(twoDimList);
}
A more efficient way to do it is to use a single list and access it by using two coordinates like the following class I have used in a previous project:
class Grid<T> {
final int length, height;
final List<T> list;
Grid(this.length, this.height) : list = List(length * height);
T get(int x, int y) => list[_getPos(x, y)];
void set(int x, int y, T value) => list[_getPos(x, y)] = value;
int _getPos(int x, int y) => x + (y * length);
}

Related

Convert (Nested List) Objects based on another variable's type

In my code, I'm creating a grid of objects. I'm trying to avoid duplication by abstracting away the loop that creates the grid and passing the specific object from outside. For example:
List<List<dynamic>> _createGridWithSameElements({
int height,
int width,
dynamic element,
}){
List<List<dynamic>> vanillaGrid = [];
for (int heightIndex = 0; heightIndex < height; heightIndex++){
List<dynamic> vanillaLine = [];
for (int widthIndex = 0; widthIndex < width; widthIndex++){
vanillaLine.add(element);
}
vanillaGrid.add(vanillaLine);
}
return vanillaGrid;
}
Then, if I wish to create a grid with string, I can:
List<List<dynamic>> emptyGrid = _createGridWithSameElements(
height: height,
width: width,
element: Cell.dead()
);
However, I would like to somehow recast the individual, atomic elements of the grid based on the type of the element. I think I have two options, neither of which I have been able to achieve:
Infer the type inside _createGridWithSameElements. But how would I do this without using List<List<dynamic>>?
Recast the grid after the _createGridWithSameElements function call. Is there a way to do this?
Use Generics to create an argument that can hold any type.
Don't forget to also, instead of passing the element itself, passing a function to generate instances of it. Otherwise you will have a grid containing the same repeated instance.
class Cell{}
void main(List arguments) {
final grid = _createGridWithSameElements(
height: 5,
width: 10,
elementGenerator: () => Cell()
);
print(grid.runtimeType); // List<List<Cell>>
}
List<List<T>> _createGridWithSameElements<T>({
int height,
int width,
T Function() elementGenerator,
}) {
final vanillaGrid = <List<T>>[];
for (int heightIndex = 0; heightIndex < height; heightIndex++) {
final vanillaLine = <T>[];
for (int widthIndex = 0; widthIndex < width; widthIndex++) {
vanillaLine.add(elementGenerator());
}
vanillaGrid.add(vanillaLine);
}
return vanillaGrid;
}
Some extra info to keep in mind:
The <T> after the function name is there to tell Dart to make T available as a generic type for that function. Any letter or word would be valid, though E, T, S, K, and V are the convention.

Trying to make a List of totals

So I have two lists that I each mapped to get the ints, and then I used a reduce function to total them.
I now need just both those totals in a new list, like a totalsList made up of TotalsEntry's or something.
How can this be done?
List<int> listOfOnlyPrices = [];
List<int> listOfOnlyExpenses = [];
int totalSales;
int totalExpenses;
void totalSalesWidget() {
listOfOnlyPrices = items.map<int>((SaleEntry int) =>
int.price).toList();
totalSales = listOfOnlyPrices.reduce((a, b) => a + b);
}
void totalExpensesWidget() {
listOfOnlyExpenses = expenseList.map<int>((ExpenseEntry int) => int.priceEx).toList();
totalExpenses = listOfOnlyExpenses.reduce((a, b) => a + b);
}
All of this works fine btw. I can use totalSales and totalExpenses already within the app.
If I understand you correctly, the following should already do the job:
List<int> get totalsList => [totalSales, totalExpenses];

Is there anything like a struct in dart?

In javascript it always bothered me people use objects as vectors like {x: 1, y: 2} instead of using an array [1,2]. Access time for the array is much faster than the object but accessing by index is more confusing especially if you need a large array. I know dart has fixed arrays but is there a way to name the offsets of an array like you would a struct or a tuple/record in another language? Define enum/constants maybe?
I'd want something like
List<int> myVector = new List([x,y]);
myVector.x = 5;
is there an equivalent or idiomatic way to do this?
That sounds like a class.
class MyVector {
int x;
int y;
MyVector(this.x, this.y);
}
There is no simpler and more efficient way to create a name-indexed structure at runtime. For simplicity you could usually use a Map, but it's not as efficient as a real class.
A class should be at least as efficient (time and memory) as a fixed length list, after all it doesn't have to do an index bounds check.
In Dart 3.0, the language will introduce records. At that point, you can use a record with named fields instead of creating a primitive class:
var myVector = (x: 42, y: 37);
print(myVector.x);
A record is unmodifiable, so you won't be able to update the values after it has been created.
For me, i see 2 way to do this. I will sort by best in my point of view
Class based method
Here, the approach is to encapsulate your need, in a dedicated object
Pros:
It's encapsultate
You can propose several way to access variable, depend of the need
You can extend functionality without break everything
I love it :p
Cons
More time spend to create class, etc.
Do you really need what i say in pros ?
Maybe weird for js people
example :
class Vector {
int x;
int y;
static final String X = "x";
static final String Y = "y";
Vector({this.x, this.y});
Vector.fromList(List<int> listOfCoor) {
this.x = listOfCoor[0];
this.y = listOfCoor[1];
}
// Here i use String, but you can use [int] an redefine static final member
int operator[](String coor) {
if (coor == "x") {
return this.x;
} else if (coor == "y") {
return this.y;
} else {
// Need to be change by a more adapt exception :)
throw new Exception("Wrong coor");
}
}
}
void main() {
Vector v = new Vector(x: 5, y: 42);
Vector v2 = new Vector.fromList([12, 24]);
print(v.x); // print 5
print(v["y"]); // print 42
print(v2.x); // print 12
print(v2[Vector.Y]); // print 24
}
Enum based method:
You can also defined a "enum" (actually not really implement but will be in the future version) that will contains "shortcut" to your value
Pros
More simple to implement
Is more like your example ;p
Cons
Less extendable
i think is not very pretty
Not OOP think
example:
class Vector {
static final int x = 0;
static final int y = 1;
}
void main() {
List<int> myVector = new List(2);
myVector[Vector.x] = 5;
myVector[Vector.y] = 42;
}
Make your choice ;p
This is only possible with a class in Dart.
There are some open feature requests at http://dartbug.com
introduce struct (lightweight class)
Give us a way to structure Bytedata
If you have reasonably big data structure, you can use "dart:typed_data" as a model and provide lightweight view for the stored data. This way the overhead should be minimal.
For example, if you need 4X4 matrix of Uint8 values:
import "dart:typed_data";
import "dart:collection";
import "package:range/range.dart";
class Model4X4Uint8 {
final Uint8List _data;
static const int objectLength = 4 * 4;
final Queue<int> _freeSlotIndexes;
Model4X4Uint8(int length): _data = new Uint8List((length) * objectLength),
_freeSlotIndexes = new Queue<int>.from(range(0, length));
int get slotsLeft => _freeSlotIndexes.length;
num operator [](int index) => _data[index];
operator []=(int index, int val) => _data[index] = val;
int reserveSlot() =>
slotsLeft > 0 ? _freeSlotIndexes.removeFirst() : throw ("full");
void delete(int index) => _freeSlotIndexes.addFirst(index);
}
class Matrix4X4Uint8 {
final int offset;
final Model4X4Uint8 model;
const Matrix4X4Uint8(this.model, this.offset);
num operator [](int index) => model[offset + index];
operator []=(int index, int val) => model[offset + index] = val;
void delete() => model.delete(offset);
}
void main() {
final Model4X4Uint8 data = new Model4X4Uint8(100);
final Matrix4X4Uint8 mat = new Matrix4X4Uint8(data, data.reserveSlot())
..[14] = 10
..[12] = 256; //overlow;
print("${mat[0]} ${mat[4]} ${mat[8]} ${mat[12]} \n"
"${mat[1]} ${mat[5]} ${mat[9]} ${mat[13]} \n"
"${mat[2]} ${mat[6]} ${mat[10]} ${mat[14]} \n"
"${mat[3]} ${mat[7]} ${mat[11]} ${mat[15]} \n");
mat.delete();
}
But this is very low level solution and can easily create sneaky bugs with memory management and overflows.
You could also use an extension on List to create aliases to specific indexes.
Although it will be difficult to set up mutually exclusive aliases, in some cases, it may be a simple solution.
import 'package:test/test.dart';
extension Coordinates<V> on List<V> {
V get x => this[0];
V get y => this[1];
V get z => this[2];
}
void main() {
test('access by property', () {
var position = [5, 4, -2];
expect(position.x, 5);
expect(position.y, 4);
expect(position.z, -2);
});
}
The Tuple package https://pub.dev/packages/tuple might be what you are looking for when a class is too heavy.
import 'package:tuple/tuple.dart';
const point = Tuple2<int, int>(1, 2);
print(point.item1); // print 1
print(point.item2); // print 2

OpenCV cv::Mat set if

Is there a simple way to set all values in a cv::Mat to a given value if they fulfill some condition. For instance, I have CV_32FC1, and I want set all values which are 0 to 20. In MATLAB I would have simply done this:
M(M == 0) = 20;
You can use
cv::Mat mask = M == 0;
M.setTo(0.5, mask);
However, it includes using additional memory for creating mask, but is a solution using opencv API therefore can be applied to all matrix types. If you consider performance issues, you can always refer directly to Mat::data to optimize this solution for concrete matrix type.
This is a classic case for look-up table. It is fast, simple, and can remap multiple values at same time.
Thanks to #marol 's comments, I settled for the implementation below. I am using C++11 lambda functions to condition which values need to be changed. To demonstrate its power, my condition is to set to DEFAULT_VAL when the value is out of the range [MIN_VAL, MAX_VAL]:
#include <functional>
#define MatType float
#define MatCmpFunc std::function<bool(const MatType&)>
.
.
.
// function which accepts lambda function to condition values which need to
// be changed
void MatSetIf(cv::Mat& inputmat, const MatType& newval, MatCmpFunc func) {
float* pmat = (float*)inputmat.data;
// iterate and set only values which fulfill the criteria
for (int idx = 0; idx < inputmat.total(); ++idx) {
if (func(pmat[idx])) {
pmat[idx] = newval;
}
}
}
.
.
.
void main() {
cv::Mat mymat(100,100,CV_32FC1);
const float MIN_VAL = 10;
const float MAX_VAL = 1000;
const float DEFAULT_VAL = -1;
.
.
.
// declare lambda function which returns true when mat value out of range
MatCmpFunc func = [&](const DepthMatType& val) -> bool {
return (val < MIN_VAL || val > MAX_VAL) ? true : false;
};
// use lambda func above to set all out of range values to 50
Mat32FSetIf(mymat, DEFAULT_VAL, func);
.
.
.
}

idiom for auto-initializing map values to 0

Is there a better idiom for auto-initializing Map values to 0 than the following? In the following code there is an asymmetry between the approach to adding a value to a target of type List versus int.
main() {
addToList(Map m, v) =>
m..putIfAbsent('foo', () => []).add(v);
///////////////////////////////////////////////////////////
// Not allowed (expression is not assignable)
// addToScalar(Map m, v) =>
// m..putIfAbsent('foo', () => 0) += 3;
addToScalar1(Map m, v) {
m.putIfAbsent('foo', () => 0);
m['foo'] += v;
return m;
}
addToScalar2(Map m, v) {
if(m.containsKey('foo')) {
m['foo'] += v;
} else {
m['foo'] = v;
}
return m;
}
print(addToList({}, 3));
print(addToScalar1({}, 3));
print(addToScalar2({}, 3));
}
Conceptually addToList and addToScalar do similar things. But the analog for the int stored as a value type might be:
m.putIfAbsent('foo', () => 0) += someValue
which will not work since what is returned from putIfAbsent is not assignable. So with both the working approaches used in the scalar case the lookup in the map for key 'foo' is being done twice. Can this be avoided with the Map API?
No, you cannot currently avoid two lookups in order to modify a map value.
We have considered, but never decided on, a way to achieve that (e.g., an "update" method).
The Two shortest/most efficient solution to your problem are:
int _returnZero() => 0; // Toplevel or static function.
...
map[key] = map.putIfAbsent(key, _returnZero) + v;
...
and:
int value = map[key];
map[key] = (value == null) ? v : value + v;

Resources