直接等同會是這個樣子:
public Transform TransformsMultiply(IEnumerable<Transform> transforms)
{
var matrices = transforms.Select(transform =>
transform.Name == "matrix"
? transform.Data
: transformToMatrix(transform));
return new Transform
{
Name = "matrix",
Data = matrices.Aggregate((a, b) =>
multiplyTransformMatrices(a, b));
};
}
你當然需要定義Transform
類和transformToMatrix
和multiplyTransformMatrices
方法;
儘管區分Name
屬性的轉換類型不是慣用的C#。這將是好得多,如果你創建了每種類型的抽象基Transform
類型和子類變換:
public abstract class Transform { /* ... */ }
public class Matrix : Transform
{
public int[,] Data { get; set; }
}
public class OtherTypeOfTransform : Transform
{
/* ... */
}
方法的第一部分將隨後樣子:
var matrices = transforms.Select(transform =>
transform is Matrix
? transform.Data
: transformToMatrix(transform));
但是,這並不是非常面向對象,因爲transformToMatrix
需要知道如何將每種類型的轉換轉換爲矩陣。您應該考慮在基類中添加抽象方法ToMatrix
並在子類中實現它,從而將自身轉換爲矩陣到每個子類的責任。
public abstract class Transform
{
public abstract Matrix ToMatrix();
}
public class Matrix : Transform
{
public int[,] Data { get; set; }
public Matrix ToMatrix() { return this; }
}
public class OtherTypeOfTransform : Transform
{
public Matrix ToMatrix()
{
// Type-specific implementation
}
}
在此之後,執行應該是這樣的:
public Matrix TransformsMultiply(IEnumerable<Transform> transforms)
{
return new Matrix
{
Data = transforms
.Select(transform => transform.ToMatrix())
.Aggregate((a, b) => multiplyTransformMatrices(a, b));
};
}
移動倍增到Matrix
可以使這個更漂亮:
public Matrix TransformsMultiply(IEnumerable<Transform> transforms)
{
return new Matrix
{
Data = transforms
.Select(transform => transform.ToMatrix())
.Aggregate((a, b) => a.MultiplyBy(b));
};
}
這就是我將如何轉換這JavaScript轉化爲慣用的面向對象的C#代碼。
編輯
你問我如何使用的Dictionary<string, decimal[]>
代替IEnumerable<Transform>
實現這一點,所以在這裏它是:
public KeyValuePair<string, decimal[]> TransformsMultiply(
Dictionary<string, decimal[]> transforms)
{
var matrices = transforms.Select(kvp =>
kvp.Key == "matrix"
? kvp.Value
: transformToMatrix(kvg.Value));
return new KeyValuePair<string, int>(
"matrix",
matrices.Aggregate((a, b) => multiplyTransformMatrices(a, b));
}
一個Dictionary<TKey, TValue>
是IEnumerable<KeyValuePair<TKey, TValue>>
,所以在這種解決方案中,變換由KeyValuePair<string, decimal[]>
表示。
請注意,字典密鑰是唯一的,所以您只能使用密鑰"matrix"
進行一次轉換。我不確定這是你想要的。
這種解決方案的缺點是:
- 你只能擁有各類型,因爲變換的一個實例字典鍵唯一
- 它掩蓋了代碼的意圖,並使其更難閱讀(在我看來,
- 邏輯上屬於轉換本身的行爲(如何將其轉換爲矩陣以及如何將矩陣乘以另一個矩陣)現在未被封裝,並且它位於
transformToMatrix
和multiplyTransformMatrices
方法中。
如果你真的想要的變換,而不是一個名爲類的通用集裝箱,可以使用Tuple<T, U>
:
public Tuple<string, decimal[]> TransformsMultiply(
IEnumerable<Tuple<string, decimal[]>> transforms)
{
var matrices = transforms.Select(t =>
t.Item1 == "matrix" ? t.Item2 : transformToMatrix(t.Item2));
return new Tuple<string, decimal[]>(
"matrix",
matrices.Aggregate((a, b) => multiplyTransformMatrices(a, b)));
}
在這裏,你可以有多種變換名稱相同,但第二個和第三個缺點上面提到的仍然適用。
您有一本字典作爲本貼子的標籤。所以字典看起來像這樣:var matrices = transforms.GroupBy(x => x.a,y => y.b) .ToDictionary(x => x.Key,y => y.ToList()); – jdweng
@jdweng謝謝。但是如果我還有一個字典作爲輸入參數「變換」呢?例如:Dictionary,其中decimal []是矩陣係數的數組? –
單個數組如何映射到(a,b)? – jdweng