在javascript中,我总是困扰着人们使用对象作为{x: 1, y: 2}
之类的向量,而不是使用数组[1,2]
。数组的访问时间比对象快得多,但是通过索引访问会更加混乱,尤其是在需要大型数组的情况下。我知道dart有固定数组,但有没有办法命名数组的偏移量,就像你在另一种语言中使用struct或tuple / record一样?可能定义枚举/常量?
我想要像
这样的东西List<int> myVector = new List([x,y]);
myVector.x = 5;
是否有相同或惯用的方法来做到这一点?
答案 0 :(得分:12)
听起来像是一堂课。
class MyVector {
final x;
final y;
const MyVector(this.x, this.y);
}
在运行时创建命名索引结构没有更简单,更有效的方法。为简单起见,您通常可以使用Map
,但它不如真正的类有效。
一个类应该与固定长度列表一样有效(时间和内存)。
答案 1 :(得分:5)
对我来说,我看到了两种方法。我会在我看来最好的排序
基于类的方法
这里,方法是将您的需求封装在专用对象
中优点:
缺点
示例:
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
}
基于枚举的方法:
你也可以定义一个&#34; enum&#34; (实际上并没有真正实现,但将在未来版本中)将包含&#34;快捷方式&#34;为了你的价值
赞成
缺点
示例:的
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;
}
做出选择; p
答案 2 :(得分:3)
这只适用于Dart中的课程。
有一些公开功能请求答案 3 :(得分:3)
如果您拥有相当大的数据结构,则可以使用"dart:typed_data"
作为模型,并为存储的数据提供轻量级视图。这样开销应该是最小的。
例如,如果您需要UX8值的4X4矩阵:
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();
}
但这是一个非常低级别的解决方案,可以轻松地创建内存管理和溢出的漏洞。
答案 4 :(得分:0)
您还可以在extension
上使用List
来创建特定索引的别名。
虽然很难设置互斥别名,但在某些情况下,这可能是一个简单的解决方案。
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);
});
}