如何使用ConvertAll()转换多级数组?

sui*_*uan 2 c#

我想像这样使用ConvertAll:

 var sou = new[,] { { true, false, false }, { true, true, true } };
 var tar = Array.ConvertAll<bool, int>(sou, x => (x ? 1 : 0));
Run Code Online (Sandbox Code Playgroud)

但是我遇到了编译错误:

不能隐式转换类型bool [ , ]到bool []

Jaa*_*rus 6

你可以写一个简单的转换扩展:

public static class ArrayExtensions
{
    public static TResult[,] ConvertAll<TSource, TResult>(this TSource[,] source, Func<TSource, TResult> projection)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (projection == null)
            throw new ArgumentNullException("projection");  

        var result = new TResult[source.GetLength(0), source.GetLength(1)];
        for (int x = 0; x < source.GetLength(0); x++)
            for (int y = 0; y < source.GetLength(1); y++)
                result[x, y] = projection(source[x, y]);
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

示例用法如下所示:

var tar = sou.ConvertAll(x => x ? 1 : 0);
Run Code Online (Sandbox Code Playgroud)

不利的一面是,如果你想做除了投影之外的任何其他变换,你将会陷入困境.


或者,如果您希望能够在序列上使用LINQ运算符,则可以使用常规LINQ方法轻松完成.但是,您仍然需要一个自定义实现来将序列转换回2D数组:

public static T[,] To2DArray<T>(this IEnumerable<T> source, int rows, int columns)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (rows < 0 || columns < 0)
        throw new ArgumentException("rows and columns must be positive integers.");

    var result = new T[rows, columns];

    if (columns == 0 || rows == 0)
        return result;            

    int column = 0, row = 0;
    foreach (T element in source)
    {
        if (column >= columns)
        {
            column = 0;                    
            if (++row >= rows)                    
                throw new InvalidOperationException("Sequence elements do not fit the array.");                         
        }
        result[row, column++] = element;                
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

这样可以提供更大的灵活性,因为您可以将源数组作为IEnumerable {T}序列进行操作.

样品用法:

var tar = sou.Cast<bool>().Select(x => x ? 1 : 0).To2DArray(sou.GetLength(0), sou.GetLength(1));
Run Code Online (Sandbox Code Playgroud)

请注意,由于多维数组未实现通用接口,因此需要初始强制转换将序列从IEnumerable范例转换为IEnumerable<T>范例IEnumerable<T>.大多数LINQ转换只适用于此.