Emanuele Sabetta Emanuele Sabetta - 18 days ago 6
C# Question

How to render this map-reduce javascript code to an equivalent LINQ Select-Aggregate?

How to render this map-reduce javascript function to an equivalent c# LINQ Select-Aggregate syntax?

/**
* 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;

};

Answer

The direct equivalent would look something like this:

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));
    };
}

Of course you will need to define the Transform class and the transformToMatrix and multiplyTransformMatrices methods;

Though differentiating types of transforms by the Name property is not idiomatic C#. It would be much better if you created an abstract base Transform type and subclasses for each type of transform:

public abstract class Transform { /* ... */ }

public class Matrix : Transform
{
    public int[,] Data { get; set; }
}

public class OtherTypeOfTransform : Transform
{
    /* ... */
}

The first part of the method would then look like:

var matrices = transforms.Select(transform =>
    transform is Matrix 
        ? transform.Data 
        : transformToMatrix(transform));

But that is not very object oriented because transformToMatrix needs to know how to convert each type of transform into a matrix. You should consider adding an abstract ToMatrix method to the base class and implementing it in the subclasses, thereby delegating the responsibility of converting itself into a matrix to each subclass.

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
    }
}

After that, the implementation would look like this:

public Matrix TransformsMultiply(IEnumerable<Transform> transforms)
{
    return new Matrix
    {
        Data = transforms
            .Select(transform => transform.ToMatrix())
            .Aggregate((a, b) => multiplyTransformMatrices(a, b));
    };
}

Moving the multiplication into the Matrix class makes this even nicer:

public Matrix TransformsMultiply(IEnumerable<Transform> transforms)
{
    return new Matrix
    {
        Data = transforms
            .Select(transform => transform.ToMatrix())
            .Aggregate((a, b) => a.MultiplyBy(b));
    };
}

And that's how I would convert that JavaScript into idiomatic object-oriented C# code.