2013-02-19 42 views
-1

我有一個struct其中包含了一些intbool成員,我期待獲得列表中的最低值(實際進行的A *搜索基於路徑查找器) 。獲取列表的最低值<Struct.int>

基本上,我的目標是這樣的:

public struct Tile 
    { 
     public int id; 
     public int x; 
     public int y; 
     public int cost; 
     public bool walkable; 
     public int distanceLeft; 
     public int parentid; 
    } 

而且我想用最低的distanceLeft的項目。名單宣佈像這樣:

 List<Structs.Tile> openList = new List<Structs.Tile>(); 

和值以這種方式分配:

 while (pathFound == null) 
     { 
      foreach (Structs.Tile tile in map) 
      { 
       foreach (Structs.Tile tile1 in getSurroundingTiles(Current)) 
       { 
        if (tile1.x == tile.x && tile1.y == tile.y) 
        { 
         Structs.Tile curTile = tile1; 
         curTile.parentid = Current.id; 
         curTile.distanceLeft = (Math.Abs(tile.x - goalx) + Math.Abs(tile.y - goaly)); 
         if (curTile.distanceLeft == 0) 
         { 
          pathFound = true; 
         } 
         openList.Add(curTile); 
        } 
       } 
      } 
      foreach (Structs.Tile tile in openList) 
      { 

      } 
     } 

如果我猜我會說這要麼是非常困難或複雜得多,比我」讓它聽起來很不錯,或者非常容易,我只是感到困惑。

我的確在考慮滾動列表並將每個項目與其對應項目進行比較,但考慮到我們所處的年齡,這似乎不合理,似乎會有一種更簡單的方法。我不關心列表的順序,因爲我正在爲每個項目分配一個索引,我可以從中調用它。

在此先感謝!

+0

你應該看看LINQ。 – antonijn 2013-02-19 21:19:06

+0

爲什麼你使用一個結構?它消耗大約28個字節,比4/8字節的指針大得多。每個消耗你的結構的方法都需要攜帶28個字節。如果是班級,比較會更快。 – 2013-02-19 21:30:09

+0

它可能是一個重複的mbeckish,但我不知道Linq是否足夠知道這是一個Linq函數,所以我對此表示誠摯的歉意。儘管如此,我還是希望保留這個線程,因爲它包含了我認爲可能對某些人(其他人可能不知道Linq或此處引用的協會)有用的響應。 – XtrmJosh 2013-02-19 21:34:11

回答

2

沒有一種LINQ擴展方法可以返回具有最小值的對象,但您可以自己編寫一個。下面的類,你想要做的任何非空枚舉什麼:

public static class MyExtensions 
{ 
    public static TSource MinOf<TSource>(
     this IEnumerable<TSource> source, 
     Func<TSource, int> selector) 
    { 
     // Get the enumerator. 
     var enumerator = source.GetEnumerator(); 
     if (!enumerator.MoveNext()) 
      throw new InvalidOperationException("The source sequence is empty."); 

     // Take the first value as a minimum. 
     int minimum = selector(enumerator.Current); 
     TSource current = enumerator.Current; 

     // Go through all other values... 
     while (enumerator.MoveNext()) 
     { 
      int value = selector(enumerator.Current); 
      if (value < minimum) 
      { 
       // A new minimum was found. Store it. 
       minimum = value; 
       current = enumerator.Current; 
      } 
     } 

     // Return the minimum value. 
     return current; 
    } 
} 

把它放在一個文件在您的項目,並調用它像這樣:

openList.MinOf(tile => tile.distanceLeft); 

這比訂貨整個更有效率序列(使用OrderBy),然後取第一個值(使用First)。

+0

謝謝,這個方法會返回對象本身,或者只是存儲在目的?我通過觀察它來確定對象? – XtrmJosh 2013-02-19 21:29:44

+0

不,它返回int。我用會返回對象的東西更新了答案。 – Virtlink 2013-02-19 21:32:43

+0

謝謝,這看起來非常複雜,但我需要一段時間才能理解它。看來這是「正確」的方式,所以非常感謝! – XtrmJosh 2013-02-19 21:37:28

1

要獲得Tile具有最低distanceLeft,試試這個:

Tile tile = openList.OrderByAscending(t => t.distanceLeft).First(); 

編輯:

這樣做會返回一個IEnumerable<Tile>將在升序進行排序 - openList本身不會改性。

+0

這會修改列表的順序嗎?如果是這樣,我認爲Linq的選擇可能是有利的,我知道我提到我不介意修改順序,但我寧願不是爲了資源,也不是爲了做什麼,看起來可能有點浪費這個。儘管如此,我非常感謝您的回覆。謝謝! – XtrmJosh 2013-02-19 21:36:13

+0

@XtrmJosh看我的編輯。 – 2013-02-19 21:38:51

+0

它不修改輸入列表。相反,它會創建一些內存結構,對整​​個列表進行排序,然後除了第一個元素外,它們全部被丟棄。 – Virtlink 2013-02-19 21:42:50

1

或者,如果由於某種原因,你不能使用LINQ:

int lowest = 0; 
for (int i = 1; i < openList.Count; ++i) 
{ 
    if (openList[i].distanceLeft < openList[lowest].distanceLeft) 
    { 
     lowest = i; 
    } 
} 
// lowest contains the index of the item with the lowest 'distanceLeft' value. 
// You can return the item itself by indexing into the list. 
var lowestItem = openList[lowest]; 
+0

這將返回最小值,而不是具有最小值的對象 – 2013-02-19 21:41:15

+0

只是爲了讓您更清楚地瞭解爲什麼在這種情況下您不能使用Min():'Min()'返回對象,但將對象本身(你不能指定選擇器)。 'Min(lambda)'返回lambda選擇的數據類型,在本例中爲int。 – gunr2171 2013-02-19 21:54:41

+0

實際上,它是以最小值返回項目的索引。現在它返回項目本身。 – 2013-02-19 21:55:20

5

其他的答案解釋如何使用LINQ做到這一點 - 不過,他們都是O(n)或更慢。使用其中的一種方法將顯着減慢您的尋路算法

取而代之,你的應該使用正確的數據結構。而不是列表,您應該將您的節點存儲在優先級隊列中,以獲得(併除去)中的最小值O(log n)

請參閱this question瞭解.Net中的優先級隊列列表。

+0

這取決於您通常如何使用集合。如果你想索引它,一個優先級隊列將是一個相當差的數據結構選擇。 – 2013-02-19 21:58:11

+1

@Jim:他在這個問題中表示他希望將它用於[A \ *](http://en.wikipedia.org/wiki/A*_search_algorithm#Description) – 2013-02-19 22:12:07

+0

啊......錯過了。那麼優先隊列肯定是要走的路。 – 2013-02-19 22:17:20