将jagged char [] []转换为char [,]?

时间:2012-08-17 17:52:30

标签: c# arrays

我昨天开始的一个'为了它的地狱'项目是Befunge翻译。除了边缘情况之外,我大部分都在工作。

我很懒,决定用一个befunge程序阅读:

char[][] program = File.ReadAllLines(args[0]).Select(x => x.ToCharArray()).ToArray();

我知道自己后来为自己创造了更多的工作,但我想到达其他部分并将其留在那里。现在是时候了,我需要解决program不是矩形的事实。假设我有这个befunge程序:

v   v   <
    @
>       ^

第1行和第3行长度为9个字符,但第2行只有5个。在设置我的befunge解释器的方式中,我会在程序终止之前得到IndexOutOfBoundsException,因为在解释{{ 1}}作为方向的改变,我会尝试访问^program[1][8]只有5长。我不是试图捕捉异常并围绕它跳舞,而是如何使用program[1]创建char[,]并用空格填充额外的字符?

我知道我可以确定最长行的长度,行数,创建char [,]并将它们复制过来,但我希望有一些更简单,更优雅的东西。如果新方法更好,我完全可以抛出上述内容。

3 个答案:

答案 0 :(得分:2)

不是重新创建整个锯齿状数组(假设它可能相当大),你可以为它创建一个包装器。该包装器能够进行边界检查并返回一些默认值,如果它超出界限而不是错误。

public class Matrix<T>
{
  public T[][] UnderlyingCollection {get;set;} //should probably be readonly and set in the constructor

  public T DefaultValue {get;set;}

  public T this[int i, int j]
  {
    get
    {
      if(UnderlyingCollection.Length > i && UnderlyingCollection[i].Length > j)
        return UnderlyingCollection[i][j];
      else
        return DefaultValue;
    }
    set
    { /*TODO implement*/ }

  }
}

答案 1 :(得分:2)

在@ AndreCalil之前的答案的基础上,这可能更高效,特别是对于大型原始类型的数组。原始类型的数组可以被视为字节的平缓冲区,这在这种工作中很有用(如果你有汇编程序或C的经验):

static void Main( string[] args )
{
    string[][] jagged = new string[][] { new string[] { "alpha" ,                                              } ,
                                            new string[] { "bravo" , "charlie" ,                                  } ,
                                            new string[] { "delta" , "echo"    , "foxtrot" ,                      } ,
                                            new string[] { "golf"  , "hotel"   , "india"   , "juliet" ,           } ,
                                            new string[] { "kilo"  , "lima"    , "mike"    , "nancy"  , "oscar" , } ,
                                        } ;
    string[,]  rectangular = RectArrayFromJagged<string>( jagged ) ;

    return;
}

public static T[,] RectArrayFromJagged<T>( T[][] a )
{
    int  rows  = a.Length;
    int  cols  = a.Max( x => x.Length );
    T[,] value = new T[ rows , cols ] ;

    value.Initialize() ;

    if ( typeof(T).IsPrimitive )
    {
        int elementSizeInOctets = Buffer.ByteLength(value) / value.Length ;
        for ( int i = 0 ; i < rows ; ++i )
        {
            int rowOffsetInOctets = i * cols    * elementSizeInOctets ;
            int rowLengthInOctets = a[i].Length * elementSizeInOctets ;
            Buffer.BlockCopy( a[i] , 0 , value , rowOffsetInOctets , rowLengthInOctets ) ;
        }
    }
    else
    {
        for ( int i = 0 ; i < rows ; ++i )
        {
            int rowLength = a[i].Length ;
            for ( int j = 0 ; j < rowLength ; ++j )
            {
                value[i,j] = a[i][j] ;
            }
        }
    }
    return value ;
}

答案 2 :(得分:0)

伙计,我不确定这是否是您要找的,但请查看:

public static class CharArrayExtension
{
    public static char[,] FormatMatrix(this char[][] matrix)
    {
        int TotalColumns = matrix.Length;
        int TotalLines = 0;

        //Get the longest line of the current matrix
        for (int column = 0; column < TotalColumns; column++)
        {
            int line = matrix[column].Length;

            if (line > TotalLines)
                TotalLines = line;
        }

        //Instantiate the resulting matrix
        char[,] Return = new char[TotalColumns, TotalLines];

        Return.Initialize();

        //Retrieve values from the current matrix
        for (int CurrentColumn = 0; CurrentColumn < TotalColumns; CurrentColumn++)
        {
            int MaxLines = matrix[CurrentColumn].Length;

            for (int CurrentLine = 0; CurrentLine < MaxLines; CurrentLine++)
            {
                Return[CurrentColumn, CurrentLine] = matrix[CurrentColumn][CurrentLine];
            }
        }

        return Return;
    }
}

用法:

        char[] Length5 = new char[]{ 'a', 'b', 'c', 'd', 'e'};
        char[] Length10 = new char[10];

        char[][] Matrix = new char[2][];
        Matrix[0] = Length5;
        Matrix[1] = Length10;

        char[,] FormattedMatrix = Matrix.FormatMatrix();

我们将不胜感激。


<强>更新

尼古拉斯指出了性能问题。我很好奇,所以我做了以下微弱基准测试:

        char[] Length5 = new char[]{ 'a', 'b', 'c', 'd', 'e'};
        char[] Length10 = new char[10];

        char[][] Matrix = new char[2][];
        Matrix[0] = Length5;
        Matrix[1] = Length10;

        Stopwatch stopWatch = new Stopwatch();

        stopWatch.Start();

        for (int i = 0; i < 5000; i++)
        {
            char[,] FormattedMatrix = Matrix.FormatMatrix();
        }

        stopWatch.Stop();

        Console.WriteLine(string.Format("Andre Calil: {0} ms", stopWatch.ElapsedMilliseconds));

        stopWatch.Reset();

        stopWatch.Start();

        for (int i = 0; i < 5000; i++)
        {
            char[,] FormattedMatrix = RectArrayFromJagged<char>(Matrix);
        }

        stopWatch.Stop();

        Console.WriteLine(string.Format("Nicholas Carey: {0} ms", stopWatch.ElapsedMilliseconds));

        Console.ReadLine();

我已经多次运行了,平均结果是:

Andre Calil: 3 ms
Nicholas Carey: 5 ms

我知道这不是一个合适的基准测试,但是就像我的解决方案而言,在性能方面并不是那么糟糕。