我昨天开始的一个'为了它的地狱'项目是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 [,]并将它们复制过来,但我希望有一些更简单,更优雅的东西。如果新方法更好,我完全可以抛出上述内容。
答案 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
我知道这不是一个合适的基准测试,但是就像我的解决方案而言,在性能方面并不是那么糟糕。