2016-11-20 41 views
3

如何渲染此映射 - 减少javascript函数为等效的c#LINQ Select-Aggregate语法?如何渲染此映射 - 将JavaScript代码还原为等效的LINQ Select-Aggregate?

/** 
* Multiply transforms into one. 
* 
* @param {Array} input transforms array 
* @return {Array} output matrix array 
*/ 
exports.transformsMultiply = function(transforms) { 

    // convert transforms objects to the matrices 
    transforms = transforms.map(function(transform) { 
     if (transform.name === 'matrix') { 
      return transform.data; 
     } 
     return transformToMatrix(transform); 
    }); 

    // multiply all matrices into one 
    transforms = { 
     name: 'matrix', 
     data: transforms.reduce(function(a, b) { 
      return multiplyTransformMatrices(a, b); 
     }) 
    }; 

    return transforms; 

}; 
+0

您有一本字典作为本贴子的标签。所以字典看起来像这样:var matrices = transforms.GroupBy(x => x.a,y => y.b) .ToDictionary(x => x.Key,y => y.ToList()); – jdweng

+0

@jdweng谢谢。但是如果我还有一个字典作为输入参数“变换”呢?例如:Dictionary ,其中decimal []是矩阵系数的数组? –

+0

单个数组如何映射到(a,b)? – jdweng

回答

2

直接等同会是这个样子:

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类和transformToMatrixmultiplyTransformMatrices方法;

尽管区分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"进行一次转换。我不确定这是你想要的。

这种解决方案的缺点是:

  • 你只能拥有各类型,因为变换的一个实例字典键唯一
  • 它掩盖了代码的意图,并使其更难阅读(在我看来,
  • 逻辑上属于转换本身的行为(如何将其转换为矩阵以及如何将矩阵乘以另一个矩阵)现在未被封装,并且它位于transformToMatrixmultiplyTransformMatrices方法中。

如果你真的想要的变换,而不是一个名为类的通用集装箱,可以使用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))); 
} 

在这里,你可以有多种变换名称相同,但第二个和第三个缺点上面提到的仍然适用。

+1

谢谢,这非常有帮助! –

+0

如果我有一本字典作为'变换'呢?例如:Dictionary ,其中decimal []是矩阵系数的数组?名称和数据是字典条目的键和值属性? –

+0

这也可以,但只有一个字典项目可以有关键矩阵。我不确定这是你想要的。我会用字典添加一个答案。但我不会推荐这样做。 –