2010-03-26 70 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. 拆分代码,它不是非常可读。

我sugget你打破它这种方式:

  1. 获取Y值(使用LINQ)的不同排序的集合。
  2. 对于每个Y值,使用该Y值收集所有点,按照它们的x值对它们进行排序,然后将它们添加到结果集合中(再次使用LINQ)。

如果你能够阅读VB代码,我会附上一个示例代码。我认为它会比现在的方法简单明了。

+0

如果你已经写好了,我可以读VB一点。 – 2010-03-26 15:21:14

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)); 
    } 
} 

分手SortedY成二维阵列是棘手的部分。