2010-03-26 5 views
1

나는 ICollection<MapNode>이 있습니다. 각 MapNode에는 Position 속성이 있으며 Point입니다. 이 점을 먼저 Y 값으로 정렬 한 다음 X 값으로 정렬하고이를 다차원 배열 (MapNode[,])에 넣으려고합니다.C# : 컬렉션을 다차원 배열에 맞추는 깨끗한 방법?

컬렉션은 다음과 같이 보일 것입니다 :

(30, 20) 
(20, 20) 
(20, 30) 
(30, 10) 
(30, 30) 
(20, 10) 

그리고 최종 제품을 : 여기

(20, 10) (20, 20) (20, 30) 
(30, 10) (30, 20) (30, 30) 

내가 그것을 수행하는 때우기 코드입니다. 이 끔찍한 읽을 수 있습니까? 나는 그것이 필요 이상으로 해킹 된 것처럼 느낍니다.

private Map createWorldPathNodes() 
    { 
     ICollection<MapNode> points = new HashSet<MapNode>(); 
     Rectangle worldBounds = WorldQueryUtils.WorldBounds(); 

     for (float x = worldBounds.Left; x < worldBounds.Right; x += PATH_NODE_CHUNK_SIZE) 
     { 
      for (float y = worldBounds.Y; y > worldBounds.Height; y -= PATH_NODE_CHUNK_SIZE) 
      { 
       // default is that everywhere is navigable; 
       // a different function is responsible for determining the real value 
       points.Add(new MapNode(true, new Point((int)x, (int)y))); 
      } 
     } 

     int distinctXValues = points.Select(node => node.Position.X).Distinct().Count(); 
     int distinctYValues = points.Select(node => node.Position.Y).Distinct().Count(); 

     IList<MapNode[]> mapNodeRowsToAdd = new List<MapNode[]>(); 

     while (points.Count > 0) // every iteration will take a row out of points 
     { 
      // get all the nodes with the greatest Y value currently in the collection 
      int currentMaxY = points.Select(node => node.Position.Y).Max(); 
      ICollection<MapNode> ythRow = points.Where(node => node.Position.Y == currentMaxY).ToList(); 

      // remove these nodes from the pool we're picking from 
      points = points.Where(node => ! ythRow.Contains(node)).ToList(); // ToList() is just so it is still a collection 

      // put the nodes with max y value in the array, sorting by X value 
      mapNodeRowsToAdd.Add(ythRow.OrderByDescending(node => node.Position.X).ToArray()); 
     } 

     MapNode[,] mapNodes = new MapNode[distinctXValues, distinctYValues]; 

     int xValuesAdded = 0; 
     int yValuesAdded = 0; 
     foreach (MapNode[] mapNodeRow in mapNodeRowsToAdd) 
     { 
      xValuesAdded = 0; 
      foreach (MapNode node in mapNodeRow) 
      { 
       // [y, x] may seem backwards, but mapNodes[y] == the yth row 
       mapNodes[yValuesAdded, xValuesAdded] = node; 
       xValuesAdded++; 
      } 
      yValuesAdded++; 
     } 

     return pathNodes; 
    } 

위의 기능은 꽤 잘 작동하는 것으로 보이지만 아직 방탄 테스트를 거치지 않았습니다.

답변

1
  1. 당신은 당신의 결과는 꽤 매트릭스에 맞게려고하고 있다는 것을 확실히 알고하지 않는 한, 다차원 배열 대신 가변 배열 사용을 고려할 수 있습니다.

  2. 코드를 분할하면 읽을 수 없습니다.

난 당신이 이런 식으로 휴식 제안 해 드릴 것 :

  1. 이 (LINQ를 사용하여) Y 값의 별개의 분리 수거를 가져옵니다.
  2. 각 Y 값에 대해 해당 y 값이있는 모든 점을 모아서 x 값으로 정렬하고 결과 컬렉션에 다시 추가합니다 (다시 LINQ 사용).

VB 코드를 읽을 수 있으면 샘플 코드를 첨부합니다. 나는 그것이 당신의 현재 방법보다 더 간단하고 분명해질 것이라고 생각한다. 2 차원 어레이로 SortedY 헤어지는

+0

VB를 조금이라도 읽을 수 있습니다. 이미 쓰여 있다면 조금 있습니다. –

0
int[,] source = { {30, 20}, {20, 20}, {20, 30}, {30, 10}, {30, 30}, {20, 10} } ; 

List<KeyValuePair<int, int>> listSource = new List<KeyValuePair<int,int>>(); 

for(int i=0; i < source.GetLength(0); i++) 
    listSource.Add(new KeyValuePair<int,int>(source[i,0], source[i,1])); 

var result = from l in listSource 
       group l by l.Key into grp 
       from g in grp 
       orderby g.Key, g.Value 
       select new 
       { 
       g.Key, 
       g 
       }; 

int key = 0; 
foreach(var r in result) 
{ 
    if(key != r.Key) 
    { 
     Console.WriteLine(); 
     key = r.Key; 
    } 
    Console.Write("{0}, {1} | ", r.g.Key, r.g.Value); 
} 
0
public class MapNode 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 

    public MapNode(int x, int y) 
    { 
     X = x; 
     Y = y; 
    } 
} 

public static class Sorter 
{ 
    public static void Sort(ICollection<MapNode> nodes) 
    { 
     IEnumerable<MapNode> sortedX = nodes.OrderBy(mapnode => mapnode.X); 
     IEnumerable<MapNode> sortedY = sortedX.OrderBy(mapnode => mapnode.Y); 
     Array.ForEach(sortedY.ToArray(), mn => Console.WriteLine("{0}, {1}", mn.X, mn.Y)); 
    } 
} 

까다로운 부분이다.

관련 문제