snippetcsharpMinor
How to refactor this groupby alike method but with index?
Viewed 0 times
thismethodwithbutgroupbyalikehowindexrefactor
Problem
I have got such 2d jagged array (row is 1st dimension, column is 2nd dimension, bottom to up, left to right)
I would like to get a 2d jagged array summarize the positions of consecutive elements for each row, and ignore all
the ideal outcome would be
this is my code, i feel it is not that readable, so I appreciate any suggestion in C# or F# (Linq extension method is welcomed as well)
0 0 b b b c
0 0 h g g c
0 0 h a a c
0 0 f f d d
0 0 i j e e
0 0 i j 0 0I would like to get a 2d jagged array summarize the positions of consecutive elements for each row, and ignore all
0 or single elements (assume that things like x x x y x x would not occur, so there won't be 2 blocks of same chars in a row)the ideal outcome would be
{(b,3,5,2)} // char, length, rowID, columnID
{(g,2,4,3)}
{(a,2,3,3)}
{(f,2,2,2), (d,2,2,4)}
{(e,2,1,4)}
{}this is my code, i feel it is not that readable, so I appreciate any suggestion in C# or F# (Linq extension method is welcomed as well)
Tuple[][] GetHorizontalBricks()
{
List[]> ret = new List[]>();
for (int rowID = 0; rowID > rowBricks = new List>();
var row = myBoard[rowID];
int recentCount = 1;
int columnID = 0;
while (columnID 1 && recent != '0')
{
rowBricks.Add(Tuple.Create(recent, recentCount, rowID, columnID));
}
columnID = next;
recentCount = 1;
}
ret.Add(rowBricks.ToArray());
}
return ret.ToArray();
}Solution
First of all get rid of these tuples. After one week you will forget what each int represents. Define simple struct/class for your brick.
Second thing, small performance suggestion for big row count - explicit initial list size:
without it, list would be recreated and rewritten every 4 new elements.
Below is mine implementation with linq extensions. Probably it is not faster. I don't know if it is more readable, but at least line count is smaller :)
and Console app test:
Second thing, small performance suggestion for big row count - explicit initial list size:
... = new List[]>(myBoard.Length);//assuming myBoard is an arraywithout it, list would be recreated and rewritten every 4 new elements.
Below is mine implementation with linq extensions. Probably it is not faster. I don't know if it is more readable, but at least line count is smaller :)
public struct Brick
{
public char Symbol { get; set; }
public int Length { get; set; }
public int RowID { get; set; }
public int ColumnID { get; set; }
public override string ToString()
{
return string.Format("{0} {1} {2} {3}", Symbol, Length, RowID, ColumnID);
}
}
public Brick[][] GetHorizontalBricks(char[][] board)
{
return
board
.Reverse() //bottom up row order
.Select((row,rowIndex) =>
row
.Select((c,i) => new { c = c, i = i })
.GroupBy(symbol => symbol.c) //assumption that we will never see 2 groups of same nonzero character in single row
.Where(symbol => symbol.Key != 0 && symbol.Count() > 1)
.Select(brick =>
new Brick
{
Symbol = brick.Key,
RowID = rowIndex,
ColumnID = brick.First().i,
Length = brick.Count()
})
.ToArray()
)
.Reverse() //reverse again to show result in form like you provided
.ToArray();
}and Console app test:
static void Main(string[] args)
{
char[][] board = new char[][]
{
new char[] { (char)0, (char)0, 'b' ,'b','b','c'},
new char[] { (char)0, (char)0, 'h' ,'g','g','c'},
new char[] { (char)0, (char)0, 'h' ,'a','a','c'},
new char[] { (char)0, (char)0, 'f' ,'f','d','d'},
new char[] { (char)0, (char)0, 'i' ,'j','e','e'},
new char[] { (char)0, (char)0, 'i' ,'j',(char)0,(char)0}
};
foreach (var row in new Program().GetHorizontalBricks(board))
{
Console.WriteLine("Row:");
foreach (var brick in row)
Console.WriteLine(brick);
}
Console.ReadLine();
}Code Snippets
... = new List<Tuple<char, int, int, int>[]>(myBoard.Length);//assuming myBoard is an arraypublic struct Brick
{
public char Symbol { get; set; }
public int Length { get; set; }
public int RowID { get; set; }
public int ColumnID { get; set; }
public override string ToString()
{
return string.Format("{0} {1} {2} {3}", Symbol, Length, RowID, ColumnID);
}
}
public Brick[][] GetHorizontalBricks(char[][] board)
{
return
board
.Reverse() //bottom up row order
.Select((row,rowIndex) =>
row
.Select((c,i) => new { c = c, i = i })
.GroupBy(symbol => symbol.c) //assumption that we will never see 2 groups of same nonzero character in single row
.Where(symbol => symbol.Key != 0 && symbol.Count() > 1)
.Select(brick =>
new Brick
{
Symbol = brick.Key,
RowID = rowIndex,
ColumnID = brick.First().i,
Length = brick.Count()
})
.ToArray()
)
.Reverse() //reverse again to show result in form like you provided
.ToArray();
}static void Main(string[] args)
{
char[][] board = new char[][]
{
new char[] { (char)0, (char)0, 'b' ,'b','b','c'},
new char[] { (char)0, (char)0, 'h' ,'g','g','c'},
new char[] { (char)0, (char)0, 'h' ,'a','a','c'},
new char[] { (char)0, (char)0, 'f' ,'f','d','d'},
new char[] { (char)0, (char)0, 'i' ,'j','e','e'},
new char[] { (char)0, (char)0, 'i' ,'j',(char)0,(char)0}
};
foreach (var row in new Program().GetHorizontalBricks(board))
{
Console.WriteLine("Row:");
foreach (var brick in row)
Console.WriteLine(brick);
}
Console.ReadLine();
}Context
StackExchange Code Review Q#16153, answer score: 2
Revisions (0)
No revisions yet.