2011-02-23 168 views
0

考慮以下收集如何返回一個項目的周邊項目在LINQ查詢

var players = new[]{ 
    new {Id = 1, Name = "A", Score = 70}, 
    new {Id = 2, Name = "B", Score = 50}, 
    new {Id = 3, Name = "C", Score = 100}, 
    new {Id = 4, Name = "D", Score = 90} 
}; 

如果我想(與ID = 1的發言權,播放器)通過有序上面所列內容返回特定球員的位置進球我可以寫這樣的查詢:

var result = players.OrderByDescending(p => p.Score) 
      .Select((p, i) => new {player = p, Position = i}) 
      .Where(x => x.player.Id == 1) 
      .First(); 
int position = result.Position; 
var player = result.player; 

現在我怎麼可以藉此更進一步,除了返回周邊項目實際的播放器?當我們按分數排列名單時,相鄰的項目是上一個和下一個玩家以及他們各自的位置。

下面是查詢

var expectedResult = new[]{ 
    new {Id = 2, Name = "B", Score = 50}, //Previous player 
    new {Id = 1, Name = "A", Score = 70}, 
    new {Id = 4, Name = "D", Score = 90} //Next Player 
}; 

的預期結果可能以上的結果由單個LINQ表達式實現? 任何幫助,將不勝感激。

回答

1

我會寫這樣的事:

public static IEnumerable<IList<T>> GetOverlappingChunks<T>(
    this IEnumerable<T> sequence, int chunkSize) 
{ 
    List<T> chunk = new List<T>(chunkSize); 

    foreach (var elt in sequence) 
    { 
     chunk.Add(elt); 

     if (chunk.Count > chunkSize) 
      chunk.RemoveAt(0); 

     if (chunk.Count == chunkSize) 
      yield return chunk.ToArray(); 
    } 
} 

// ... 

var result = players.OrderByDescending(p => p.Score) 
      .GetOverlappingChunks(3) 
      .Where(x => x[1].Id == 1); 

(太糟糕了,C#沒有按」 t有一個內置的deque類型。)

如果您需要處理列表中少於三名球員的情況,那麼您需要稍微調整GetOverlappingChunks和檢查。

4

您可以使用.NET 4.0中定義的郵編操作,或者使用在Rx擴展定義的掃描操作:

拉鍊:

var result = players.OrderByDescending(p => p.Score) 
    .Select((p, i) => new {Player = p, Position = i}) 
    .ToList(); //forces evaluation 

result.Zip(result.Skip(1), (i,j) => new {First= i, Second=j}) 
     .Zip(result.Skip(2), (i,j) => new {First = i.First, Second = i.Second, Third=j}) 
     .First(o => o.Second.player.Id == 1); 

但是,這不會給你的鄰居第一個也是最後一個玩家。如果你希望他們也一樣,你要按摩你的集合(因爲所有三個IEnumerable的必須具有相同數量的項目)

+0

您還需要一個關係的規則,因爲分數不是總的順序。 – 2011-02-23 15:16:20

+0

感謝您的及時迴應。爲了簡單起見,我想返回的鄰居數量設置爲2(前一個和後一個)。在現實生活中,我有可能有一個非常大的列表,我想返回50個鄰居,我看不到你的解決方案如何允許。 – Payman 2011-02-23 15:30:13