我的建议是,如果您使用复杂结构,则不应再使用标准结构,而应创建表示您建模的数据以及您可以对这些对象执行的操作的类。
显然您的程序具有Matrix 的概念(不确定您是否在英语数学中使用相同的术语)
一个 M 乘 N 的矩阵有 M 列和 N 行。
我不确定将您的abcarray 放在一个 3 x 1 的矩阵中是否明智,或者您是否想将它放在一个特殊的类中,您可以称之为 Vector。也许向量是 N 乘 1 矩阵的派生类?还是 1 乘 N?
无论如何,显然你可以对两个向量进行操作:
class Vector
{
public Matrix<T> CartesianProduct(Vector<T> v)
{
return CartesianProduct(this, v);
}
public static Matrix<T> CartesianProduct(Vector<T> x, Vector<T> y) {...}
用法如下:
Vector<string> x = new Vector<string>(new string[] { "a", "b", "c" });
Vector<string> y = new Vector<string>(new string[] { "1", "2", "3" });
Matrix<string> m = x.CartesianProduct(y);
嗯,这对我来说已经足够整洁了,所以让我们继续这条路吧。
一个向量有一个Dimension。创建 Vector 对象时,您必须指定 Dimension。在 Vector 的生命周期内,您无法更改其 Dimension。
一个向量有Coordinates,编号从0到Dimension-1。您可以获取和设置特定的坐标。为简单起见,我们使用索引来访问坐标。
您可以对向量执行的操作:加/减/负/乘/...这有点超出您的问题范围,所以我不会讨论这个。
class Vector<T> : IReadonlyCollection<T>
{
private readonly T[] coordinates;
public Vector(int dimension)
{
// TODO: check dimension > 0;
this.coordinates = new T[dimension];
}
public Vector(IEnumerable<T> data)
{
// TODO: check data != null; check data contains at least one element
this.Coordinates = data.ToArray();
}
// TODO: other constructors? ICloneable?
// TODO: Add / Subtract / Multiply with a number?
public T this[int index]
{
get => this.coordinates[index];
set => this.coordinates[index] = value;
}
}
IReadOnlyCollection 的实现相当简单:
public int Count => this.coordinates.Length;
public Enumerator<T> GetEnumerator()
{
return this.Coordinates.GetEnumerator();
}
IEnumerator Enumerable.GetEnumerator()
{
return this.GetEnumerator();
}
对于初始化,以下扩展方法会很好。如果你不熟悉扩展方法,请阅读extension methods demystified
public static Vector<T> AsVector<T>(IEnumerable<T> source)
{
return new Vector<T>(source.ToArray());
}
用法:
var abcArray = new string[] { "a", "b", "c" };
var abcVector = abcArray.AsVector();
我将矩阵设计为不可更改的二维数组。
class Matrix<T>
{
private readonly T[,] elements;
public Matrix(int columnCount, int rowCount)
{
this.elements = new T[columnCount, rowCount];
}
public Matrix(T[,] elements)
{
this.elements = elements;
}
public int RolumnCount => this.elements.GetLength[0];
public int RowCount => this.elements.GetLength[1];
// etc, invent several other useful operations on matrices.
// addition, multiplication, linear transformation, ...
}
当然,如果你真的想将 Matrix 解释为二维数组:
public T[,] Elements => this.elements
最后是两个向量的笛卡尔积,返回一个矩阵。问题是,我们需要一个函数来“组合”一个 x 坐标和一个“y”坐标。对于一个数字向量,这可能是一个乘法,对于一个字符串向量,您要使用连接。
public static Matrix<T> CartesianProduct(Vector<T> vectorX, Vector<T> vectorY,
Func<T, T, T> combine)
{
// TODO: input not null; correct dimension
IEnumerable<T> combinations = vectorX.SelectMany(vectorY,
(xCoordinate, yCoordinate) => combine(xCoordinate, yCoordinate);
return new Matrix<T>(combinations);
}
Vector<string> abcArray = new Vector<string>(new string[] { "a", "b", "c" });
Vector<string> xyzArray = new Vector<string>(new string[] { "1", "2", "3" });
Matrix<string> m = Vector.CartesianProduct(abcArray, xyzArray, (x, y) => x + y);