2011-02-23 46 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