FunVec2T Class
A unified functional 2-dimensional collection.
It does not hold the data, rather provides a unified view over different sources of data providing indexed access to collection elements.
Takes a functional approach; i.e., the following closures are defined and stored on construction:
- closure to get the jagged lengths in all dimensions;
- closure to get element at the given indices (also the bounds-checked version GetOrNone, in addition to direct access by indices);
- closure to get the collection as IEnumerable.
The allocation is limited by these closures.
The data is not re-allocated, or memoized.
For instance, if a unified collection is defined to always return a contant value,
and have a length of 1000 collections in the first dimension,
and 1000 elements in the second dimension for each of the collection;
there will NOT be an underlying array storing the same value 1_000_000 times.
To clarify that the unified collection only holds a reference, consider the following example.
int[][] underlyingArray = new int[] { new int[] { 0, 10 }, new int[] { 1, 11, 111, 1111 }, new int[] { 2, 22, 222 } };
FunVec2<int> jagged = new(underlyingArray);
Assert(underlyingArray[1][0] == 1 and jagged[1, 0] == 1);
underlyingArray[1][0] = 42;
Assert(underlyingArray[1][0] == 42 and jagged[1, 0] == 42);
To further illustrate, consider the following with underlying list of lists.
List<List<char>> underlyingList = new() { new() { 'a', 'b', 'c', 'd' }, new() { 'u', 'v' } };
FunVec2<char> jagged = new(underlyingList);
Assert(underlyingList.Count == 2 and jagged.Length1 == 2);
underlyingList.Add(new() { 'x', 'y', 'z' });
Assert(underlyingList.Count == 3 and jagged.Length1 == 3);
Assert(underlyingList[0].Count == 4 and jagged.Length2(0) == 4);
underlyingList[0].Add('e');
Assert(underlyingList[0].Count == 5 and jagged.Length2(0) == 5);
The unified jagged collection exposes a unified interface for the following methods:
- Length1: length in the first dimension (i.e., number of 1D collections).
- Length2(i): length of the i-th collection in the second dimension (i.e., number of elements in the i-th 1D collection).
- this[i]: i-th D1 collection.
- this[i,j]: element at the (i,j)-th position (i.e., j-th element of the i-th 1D collection).
- GetOrNone(i, j): returns Some of the element at the (i,j)-th position if indices are valid; None otherwise.
- AsEnumerable(): returns the collection as IEnumerable; particularly useful for linq calls over the collection.
Namespace: Orx.Fun.FunVecAssembly: Orx.Fun.FunVec (in Orx.Fun.FunVec.dll) Version: 1.0.0
public class FunVec2<T> : IEnumerable<FunVec1<T>>,
IEnumerable
- Inheritance
- Object FunVec2T
- Implements
- IEnumerableFunVec1T, IEnumerable
Type Parameters
- T
- Type of the innermost elements of the collection.
FunVec2T(T) |
2-dimensional jagged collection lengths and values of which are determined by the underlying array.
var array = new char[][] { new char[] { 'a', 'b', 'c' }, new char[] { 'd' } };
FunVec2<char> jagged = new(array);
Assert(jagged.Length1 == 2);
Assert(jagged.Length2(0) == 3);
Assert(jagged.Length2(1) == 1);
Assert(jagged[0, 2] == 'c');
Assert(jagged.GetOrNone(1, 0) == Some('d'));
Assert(jagged.GetOrNone(0, 3).IsNone);
Assert(jagged.GetOrNone(2, 0).IsNone);
|
FunVec2T(ListListT) |
2-dimensional jagged collection lengths and values of which are determined by the underlying list.
var list = new List<List<char>>() { new() { 'a', 'b', 'c' }, new() { 'd' } };
FunVec2<char> jagged = new(list);
Assert(jagged.Length1 == 2);
Assert(jagged.Length2(0) == 3);
Assert(jagged.Length2(1) == 1);
Assert(jagged[0, 2] == 'c');
Assert(jagged.GetOrNone(1, 0) == Some('d'));
Assert(jagged.GetOrNone(0, 3).IsNone);
Assert(jagged.GetOrNone(2, 0).IsNone);
|
FunVec2T(FuncInt32, Int32, T, OptInt32, OptFuncInt32, Int32) |
2-dimensional jagged collection with optional lengths, values of which are determined by the getValue function.
static int GetDistance(int from, int to) { return Math.Abs(to - from); }
FunVec2<int> distances = new(GetDistance);
Assert(distances.Length1 == int.MaxValue); // since length1 is omitted
Assert(distances.Length2(100) == int.MaxValue); // since length2 is omitted
Assert(distances[1, 2] == 1);
Assert(distances[10, 5] == 5);
FunVec2<int> distancesUpTo4 = new(GetDistance, Some(4));
Assert(distancesUpTo4.Length1 == 4);
Assert(distancesUpTo4[3, 1] == 2);
// Assert(distancesUpTo4[5, 1] == 4); // out-of-bounds, throws!
Assert(distancesUpTo4.GetOrNone(5, 1).IsNone);
FunVec2<int> distancesUpTo4 = new(GetDistance, Some(4), Some<Func<int, int>>(i => 2*i));
Assert(distancesUpTo4.Length1 == 4);
Assert(distancesUpTo4.Length2(2) == 4);
Assert(distancesUpTo4[3, 5] == 2);
// Assert(distancesUpTo4[3, 6] == 3); // out-of-bounds, throws!
// Assert(distancesUpTo4[4, 0] == 4); // out-of-bounds, throws!
Assert(distancesUpTo4.GetOrNone(3, 6).IsNone); // since Length2(3) is 6, index 6 is out of bounds.
Assert(distancesUpTo4.GetOrNone(4, 0).IsNone); // since Length1 is 4, index 4 is out of bounds.
|
FunVec2T(T, OptInt32, OptFuncInt32, Int32) |
2-dimensional jagged collection with optional lengths, which always yields the same constant value.
var agentSmith = GetSmith();
FunVec2<Agent> jagged = new(agentSmith);
Assert(jagged.Length1 == int.MaxValue); // since length1 is omitted
Assert(jagged.Length2(42) == int.MaxValue); // since length2 is omitted
Assert(jagged[0][0] == agentSmith);
Assert(jagged[42][42] == agentSmith);
Assert(jagged.GetOrNone(100, 42) == Some(agentSmith));
FunVec2<Agent> jagged = new(agentSmith, Some(50));
Assert(jagged.Length1 == 50);
Assert(jagged.Length2(42) == int.MaxValue); // since length2 is omitted
Assert(jagged[0][0] == agentSmith);
Assert(jagged[42][142] == agentSmith);
Assert(jagged.GetOrNone(100, 2).IsNone);
FunVec2<Agent> jagged = new(agentSmith, Some(50), Some<Func<int, int>>(_ => 2));
Assert(jagged.Length1 == 50);
Assert(jagged.Length2(42) == 2);
Assert(jagged[0][0] == agentSmith);
Assert(jagged[42][1] == agentSmith);
Assert(jagged.GetOrNone(0, 2).IsNone);
Assert(jagged.GetOrNone(50, 0).IsNone);
FunVec2<Agent> jagged = new(agentSmith, Some(50), Some<Func<int, int>>(i => i));
Assert(jagged.Length1 == 50);
Assert(jagged.Length2(0) == 0);
Assert(jagged.Length2(42) == 42);
Assert(jagged[42][1] == agentSmith);
Assert(jagged.GetOrNone(1, 0) == Some(agentSmith));
Assert(jagged.GetOrNone(0, 0).IsNone);
Assert(jagged.GetOrNone(50, 0).IsNone);
|
HasUnderlyingScalar |
The unified collection might be constructed with a constant scalar value; hence, returning the scalar for all indices.
If this is the case, HasUnderlyingScalar is true; and the field UnderlyingScalar equals to Some of the underlying scalar value.
Otherwise, HasUnderlyingScalar is false and UnderlyingScalar.IsNone. // vec[i] = 10, for all i.
UniJaggedD1<int> vec = new(10);
Assert(vec[3] == 10 and vec[42] == 10);
Assert(vec.Get(12) == Some(10));
// underlying constant can be obtained by the optional UnderlyingScalar field.
Assert(vec.HasUnderlyingScalar);
Assert(vec.UnderlyingScalar.IsSome);
Assert(vec.UnderlyingScalar == Some(10));
Assert(vec.UnderlyingScalar.Unwrap() == 10);
|
Item |
Directly returns the element at the i-th position.
Use Get(Int32, Int32) for the bound-checked optional version.
var underlyingArray = new int[] { 10, 11, 12 };
FunVec1<int> vec = new(underlyingArray);
Assert(vec[1] == 11);
// var x = vec[-1]; => out-of-bounds, throws!
// var x = vec[3]; => out-of-bounds, throws!
|
Equals | (Inherited from Object) |
Finalize | (Inherited from Object) |
Get |
Safely gets the element at the i-th position; returns None if the index is invalid.
var underlyingArray = new int[] { 10, 11, 12 };
FunVec1<int> vec = new(underlyingArray);
Assert(jagvecged.Get(1) == Some(11));
Assert(vec.Get(-1).IsNone);
Assert(vec.Get(2).IsNone);
For other methods on the resulting optional, see Opt.
|
GetEnumerator |
Returns the enumerator for sub-vectors in the vector.
|
GetHashCode | (Inherited from Object) |
GetType | (Inherited from Object) |
MemberwiseClone | (Inherited from Object) |
ToString | (Inherited from Object) |
(FuncInt32, Int32, T to FunVec2T) |
2-dimensional jagged collection with optional lengths, values of which are determined by the getValue function.
static int GetDistance(int from, int to) { return Math.Abs(to - from); }
FunVec2<int> distances = new(GetDistance);
Assert(distances.Length1 == int.MaxValue); // since length1 is omitted
Assert(distances.Length2(100) == int.MaxValue); // since length2 is omitted
Assert(distances[1, 2] == 1);
Assert(distances[10, 5] == 5);
FunVec2<int> distancesUpTo4 = new(GetDistance, Some(4));
Assert(distancesUpTo4.Length1 == 4);
Assert(distancesUpTo4[3, 1] == 2);
// Assert(distancesUpTo4[5, 1] == 4); // out-of-bounds, throws!
Assert(distancesUpTo4.GetOrNone(5, 1).IsNone);
FunVec2<int> distancesUpTo4 = new(GetDistance, Some(4), Some<Func<int, int>>(i => 2*i));
Assert(distancesUpTo4.Length1 == 4);
Assert(distancesUpTo4.Length2(2) == 4);
Assert(distancesUpTo4[3, 5] == 2);
// Assert(distancesUpTo4[3, 6] == 3); // out-of-bounds, throws!
// Assert(distancesUpTo4[4, 0] == 4); // out-of-bounds, throws!
Assert(distancesUpTo4.GetOrNone(3, 6).IsNone); // since Length2(3) is 6, index 6 is out of bounds.
Assert(distancesUpTo4.GetOrNone(4, 0).IsNone); // since Length1 is 4, index 4 is out of bounds.
|
(T to FunVec2T) |
2-dimensional jagged collection with optional lengths, which always yields the same constant value.
var agentSmith = GetSmith();
FunVec2<Agent> jagged = new(agentSmith);
Assert(jagged.Length1 == int.MaxValue); // since length1 is omitted
Assert(jagged.Length2(42) == int.MaxValue); // since length2 is omitted
Assert(jagged[0][0] == agentSmith);
Assert(jagged[42][42] == agentSmith);
Assert(jagged.GetOrNone(100, 42) == Some(agentSmith));
FunVec2<Agent> jagged = new(agentSmith, Some(50));
Assert(jagged.Length1 == 50);
Assert(jagged.Length2(42) == int.MaxValue); // since length2 is omitted
Assert(jagged[0][0] == agentSmith);
Assert(jagged[42][142] == agentSmith);
Assert(jagged.GetOrNone(100, 2).IsNone);
FunVec2<Agent> jagged = new(agentSmith, Some(50), Some<Func<int, int>>(_ => 2));
Assert(jagged.Length1 == 50);
Assert(jagged.Length2(42) == 2);
Assert(jagged[0][0] == agentSmith);
Assert(jagged[42][1] == agentSmith);
Assert(jagged.GetOrNone(0, 2).IsNone);
Assert(jagged.GetOrNone(50, 0).IsNone);
FunVec2<Agent> jagged = new(agentSmith, Some(50), Some<Func<int, int>>(i => i));
Assert(jagged.Length1 == 50);
Assert(jagged.Length2(0) == 0);
Assert(jagged.Length2(42) == 42);
Assert(jagged[42][1] == agentSmith);
Assert(jagged.GetOrNone(1, 0) == Some(agentSmith));
Assert(jagged.GetOrNone(0, 0).IsNone);
Assert(jagged.GetOrNone(50, 0).IsNone);
|
(T to FunVec2T) |
2-dimensional jagged collection lengths and values of which are determined by the underlying array.
var array = new char[][] { new char[] { 'a', 'b', 'c' }, new char[] { 'd' } };
FunVec2<char> jagged = new(array);
Assert(jagged.Length1 == 2);
Assert(jagged.Length2(0) == 3);
Assert(jagged.Length2(1) == 1);
Assert(jagged[0, 2] == 'c');
Assert(jagged.GetOrNone(1, 0) == Some('d'));
Assert(jagged.GetOrNone(0, 3).IsNone);
Assert(jagged.GetOrNone(2, 0).IsNone);
|
(ListListT to FunVec2T) |
2-dimensional jagged collection lengths and values of which are determined by the underlying list.
var list = new List<List<char>>() { new() { 'a', 'b', 'c' }, new() { 'd' } };
FunVec2<char> jagged = new(list);
Assert(jagged.Length1 == 2);
Assert(jagged.Length2(0) == 3);
Assert(jagged.Length2(1) == 1);
Assert(jagged[0, 2] == 'c');
Assert(jagged.GetOrNone(1, 0) == Some('d'));
Assert(jagged.GetOrNone(0, 3).IsNone);
Assert(jagged.GetOrNone(2, 0).IsNone);
|
Length1 |
Length of the vector.
var underlyingList = new List<int> { 10, 11, 12 };
FunVec1<int> vec = new(underlyingList);
Assert(vec.Length1 == 3);
Func<int, bool> underlyingFun = i => i % 2 == 0;
vec = new(underlyingFun, length1: Some(4));
Assert(vec.Length1, 4);
Func<int, bool> underlyingFun = i => i % 2 == 0;
vec = new(underlyingFun); // omitted optional argument 'length1' defaults to None -> no limit
Assert(vec.Length1 == int.MaxValue);
|
Length2 |
Length of the jagged array in the first dimension; i.e., number of 1D collections.
var underlyingList = new List<List<int>> { new() { 1 }, new() { 2, 3, 4 } };
FunVec2<int> jagged = new(underlyingList);
Assert(jagged.Length1 == 2);
Assert(jagged.Length2(0) == 1);
Assert(jagged.Length2(1) == 3);
Func<int, int, bool> underlyingFun = (i, j) => (i + j) % 2 == 0;
FunVec2<bool> upperTriangular = new(underlyingFun, length1: Some(3), getLength2: Some<Func<int, int>>(i => i + 1));
Assert(jagged.Length1 == 3);
Assert(jagged.Length2(0) == 1);
Assert(jagged.Length2(1) == 2);
Assert(jagged.Length2(2) == 3);
FunVec2<Agent> bool = new(underlyingFun, length1: Some(2)); // omitted optional argument 'length2' defaults to None -> no limit
Assert(jagged.Length2(0) == jagged.Length2(1) == int.MaxValue);
|
UnderlyingScalar |
The unified collection might be constructed with a constant scalar value; hence, returning the scalar for all indices.
If this is the case, HasUnderlyingScalar is true; and the field UnderlyingScalar equals to Some of the underlying scalar value.
Otherwise, HasUnderlyingScalar is false and UnderlyingScalar.IsNone. // vec[i] = 10, for all i.
UniJaggedD1<int> vec = new(10);
Assert(vec[3] == 10 and vec[42] == 10);
Assert(vec.Get(12) == Some(10));
// underlying constant can be obtained by the optional UnderlyingScalar field.
Assert(vec.HasUnderlyingScalar);
Assert(vec.UnderlyingScalar.IsSome);
Assert(vec.UnderlyingScalar == Some(10));
Assert(vec.UnderlyingScalar.Unwrap() == 10);
|