LINQ: Праверка супраць кожнага іншага элемента ў спісе

У мяне ёсць клас, як паказана ніжэй

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

Цяпер у мяне ёсць спіс Элементы з рознай групоўкай ід. Скажам

List items  = GetItems();

Цяпер мне трэба групаваць на аснове груповак ідэнтыфікатара, і зрабіць праверку для кожнага элемента гэтай групы адзін супраць аднаго. Як бы я зрабіць гэта ў <�моцны> LINQ эфектыўна. Любая дапамога вельмі шануецца.

IDictionary matches = new Dictionary();

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 з'яўляюцца дублікатамі) .. Як я магу выдаліць дублікаты чэкаў

0
Мне трэба, каб праверыць розніцу ў узважванні двух элементаў у групе з больш чым допуск пункт 1. Math.abs (item1.weighting-item2.weighting)> item1.Tolerance
дададзена аўтар Lamps, крыніца
@FrancescoDeLisi Я абнавіў яго. Там няма поля называецца адказ
дададзена аўтар Lamps, крыніца
@FrancescoDeLisi Я абнавіў яго. Там няма поля называецца адказ
дададзена аўтар Lamps, крыніца
Калі ласка, вызначыце полі адказу.
дададзена аўтар Francesco De Lisi, крыніца
першы зрабіць выразны спіс GroupingId Як List <> доўгі LST = items.Select (ч => h.GroupingId) .distinct() ToList ().
дададзена аўтар Kamran Shahid, крыніца
Што менавіта чэкі вы хочаце зрабіць? Здаецца, што вы хочаце, каб кінуць усё дэталі з розніцай больш, чым памяркоўнасць, але ў гэтым выпадку вы павінны параўнаць значэння з сярэднім значэннем, але параўноўваць з іншымі значэннямі ў групе. У гэтым выпадку, калі ў вас ёсць якая-небудзь пара прадметаў з розніцай больш, чым талерантнасць вы будзеце выкідваць ўсю групу.
дададзена аўтар Kirill Bestemyanov, крыніца

6 адказы

As a simple change, try exchanging p.Id != answer.Id for p.Id > answer.Id in your groupItems.Where(...) line.

3
дададзена
Дзякуючы @Rawling яна працавала :-)
дададзена аўтар Lamps, крыніца
Выдатна, калі адказ азначае, што вы думаеце і належыць groupItems.
дададзена аўтар Francesco De Lisi, крыніца
Вельмі добры ўлоў
дададзена аўтар Sergey Berezovskiy, крыніца
Гэтак жа, як і ў маім адказе.
дададзена аўтар Serge, крыніца

As a simple change, try exchanging p.Id != answer.Id for p.Id > answer.Id in your groupItems.Where(...) line.

3
дададзена
Дзякуючы @Rawling яна працавала :-)
дададзена аўтар Lamps, крыніца
Выдатна, калі адказ азначае, што вы думаеце і належыць groupItems.
дададзена аўтар Francesco De Lisi, крыніца
Вельмі добры ўлоў
дададзена аўтар Sergey Berezovskiy, крыніца
Гэтак жа, як і ў маім адказе.
дададзена аўтар Serge, крыніца

паспрабуйце гэта

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) для калекцыі 3 прадметаў. Другая частка выбірае пары, якія адпавядаюць вашаму умове.

Я таксама выдаляў групаванне код, які вы ўжо разабраліся (пункты = groupItems).

2
дададзена
Гэта я, ці гэта сцэнар, дзе LINQ выклікае цалкам нечытэльны код?
дададзена аўтар Richard Everett, крыніца

паспрабуйце гэта

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) для калекцыі 3 прадметаў. Другая частка выбірае пары, якія адпавядаюць вашаму умове.

Я таксама выдаляў групаванне код, які вы ўжо разабраліся (пункты = groupItems).

2
дададзена
Гэта я, ці гэта сцэнар, дзе LINQ выклікае цалкам нечытэльны код?
дададзена аўтар Richard Everett, крыніца

Вы маеце на ўвазе гэта:

        var items = new List>()
        {
            new Tuple(1, 1)
            , new Tuple(1, 2)
            , new Tuple(2, 2)
            , new Tuple(2, 2)
            , new Tuple(2, 3)
            , new Tuple(3, 2)
            , new Tuple(3, 3)
            , new Tuple(4, 4)
            , new Tuple(4, 3)
            , new Tuple(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 }
        );
0
дададзена
Праверце Tuple.Create , які можа захаваць вам пару знакаў, так што вам не трэба паказаць агульныя тыпы: msdn.microsoft.com/en-us/library/dd387181.aspx
дададзена аўтар Ben Reich, крыніца
Дзякуй, я не ведаў пра тое, што карысны.
дададзена аўтар Serge, крыніца

Вы маеце на ўвазе гэта:

        var items = new List>()
        {
            new Tuple(1, 1)
            , new Tuple(1, 2)
            , new Tuple(2, 2)
            , new Tuple(2, 2)
            , new Tuple(2, 3)
            , new Tuple(3, 2)
            , new Tuple(3, 3)
            , new Tuple(4, 4)
            , new Tuple(4, 3)
            , new Tuple(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 }
        );
0
дададзена
Праверце Tuple.Create , які можа захаваць вам пару знакаў, так што вам не трэба паказаць агульныя тыпы: msdn.microsoft.com/en-us/library/dd387181.aspx
дададзена аўтар Ben Reich, крыніца
Дзякуй, я не ведаў пра тое, што карысны.
дададзена аўтар Serge, крыніца