2010-03-26 66 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成二維陣列是棘手的部分。