2013-05-28 25 views
0

检查,对每一个其他项目我有一个像下面LINQ:在列表

public class Item 
{ 
    public long Id {get;set;} 
    public long GroupingId {get;set;} 
    public long Weight {get;set;} 
    public long Tolerance {get;set;} 
} 

现在我有不同的分组标识的Items列表类。可以说

List<Item> items = GetItems(); 

现在我需要基于分组的组ID,并检查该组中的每个项目对方。我将如何有效地在LINQ中做到这一点。任何帮助非常感谢。

IDictionary<long, long[]> matches = new Dictionary<long, long[]>(); 

foreach(groupedItems in items.GroupBy(p=>p.GroupingId)) 
{  
    foreach(item in groupItems) 
    { 
    // Check item with other items in group items 
    // and if condition is correct take those 2 items. 
    // lets say the condition is 
    // (item.Weighting - other.Weighting) > item.Tolerance 
    // duplicates could be removed 
    // lets condition for 1,2 is done means no need to do 2 against 1 

    var currentItem = item;  
    var matchedOnes = 
     groupItems.Where(p => (Math.Abs(p.Weighting - currentItem.Weighting) > currentItem .Tolerance) && p.Id != currentItem.Id) 
        .ToList(); 

    if (!matchedOnes.Any()) 
     continue; 

    matches.Add(currentItem.Id, matchedOnes .Select(p=>p.Id).ToArray()); 
    } 
} 

我不喜欢上面,但其给人重复的(1,2和2,1是重复的)。我将如何删除重复检查

+1

你想要做什么检查?看起来你想抛弃所有差异超过宽容的项目,但在这种情况下,你应该将数值与平均数值进行比较,但是你可以与组中的其他数值进行比较。在这种情况下,如果你有任何差异超过容差的物品,你会扔掉整个组。 –

+0

我需要检查组中两个项目的权重差异大于项目1的容差。 Math.Abs​​(item1.weighting-item2.weighting)> item1.Tolerance – Lamps

+0

第一使GroupingId 的不同列表喜欢清单 LST = items.Select(H => h.GroupingId).Distinct()。ToList() ; –

回答

3

作为一个简单的更改,请尝试在您的groupItems.Where(...)行中交换p.Id != answer.Id代替p.Id > answer.Id

+0

非常好,如果回答意味着你的想法和属于groupItems。 –

+0

非常不错的赶上 –

+0

正如在我的答案。 – Serge

0

你的意思是这样的:

 var items = new List<Tuple<int, int>>() 
     { 
      new Tuple<int, int>(1, 1) 
      , new Tuple<int, int>(1, 2) 
      , new Tuple<int, int>(2, 2) 
      , new Tuple<int, int>(2, 2) 
      , new Tuple<int, int>(2, 3) 
      , new Tuple<int, int>(3, 2) 
      , new Tuple<int, int>(3, 3) 
      , new Tuple<int, int>(4, 4) 
      , new Tuple<int, int>(4, 3) 
      , new Tuple<int, int>(4, 4) 
     }.Select(kp => new { id = kp.Item1, data = kp.Item2 }); 

     var res = (
      from i1 in items 
      from i2 in items 
      where i1.id < i2.id 
       /* Custom Filter goes there */ 
       && i1.data == i2.data 
      select new { i1 = i1, i2 = i2 } 
     ); 
+4

查看'Tuple.Create'可以节省你几个字符,因为你不需要指定泛型类型:http://msdn.microsoft.com/en-us/library/dd387181.aspx –

+0

谢谢,我不知道那个有用的。 – Serge

-2

尝试此

var pairs = Enumerable.Range(0, items.Count()).SelectMany(index => 
    items.Skip(index + 1).Select(right => new { left = items.elementAt(index), right })); 

var matches = pairs.Where(item => 
       (item.left.Weight - item.right.Weight) > item.left.Tolerance); 

第一部分创建所有必须像(1,2),(1,3),(2,3),用于collecti待比较的对3件物品。 第二部分选择符合您的条件的配对。

我也删除了你已经想出的分组代码(items = groupItems)。

+0

是我,还是这是一个LINQ导致完全不可读代码的场景? –