C# Linq Сравнение значений списка с использованием нескольких полей и возвращаемого элемента, который не удовлетворяет условию - PullRequest
0 голосов
/ 20 июня 2020

У меня есть такой список под названием результат

{ Id = "8131367", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131368", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 1500.00 }
{ Id = "8131369", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131370", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131371", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131372", GId = 27720, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131373", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131374", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131375", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131376", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 500.00 }
{ Id = "8131377", GId = 27721, Share = 1.0000, Type = "1029", OPC = "997", IPC = "997", Price = 1500.00 }

Мне нужно отфильтровать список на основе GId, Share, Type, OP C, IP C, имеющего одинаковые значения и цена, имеющая различное значение. Итак, второй и последний из списка имеют другую цену. Поэтому мне нужно получить этот список или свойство Id из элемента списка, цена которого отличается, а остальные значения одинаковы.

Используя два цикла Foreach Я смог получить то, что мне было нужно, но, к сожалению, меня попросили преобразовать это в запрос LINQ. это то, что я пробовал

var items = result.Select(r => result.Where(rr => (r.GId == rr.GId) 
                                                   && (r.Share == rr.Share) 
                                                   && (r.Type == rr.Type) 
                                                   && (r.IPC == rr.IPC) 
                                                   && (r.OPC == rr.OPC) 
                                                   && (r.Price != rr.Price))).ToList();

Но из приведенного выше запроса я не получаю то, что хотел, я считаю, что близок к тому, что мне нужно, но мне не хватает опыта с LINQ.

Ответы [ 3 ]

1 голос
/ 20 июня 2020

Вы можете использовать Группировать по , чтобы сгруппировать все свойства, кроме Id, как следующий код:

var items = result.GroupBy(x => new { x.GId, x.Share, x.Type, x.OPC, x.IPC, x.Price })
    .Where(x => x.Count() == 1)
    .SelectMany(x => x.Take(1))
    .ToList();

Демо

foreach(Test item in items)
{
    Console.WriteLine($"Id:{item.Id}, GID:{item.GId}, Price:{item.Price}");
}

Результат

Id:8131368, GID:27720, Price:1500
Id:8131377, GID:27721, Price:1500

Надеюсь, вы найдете это полезным.

1 голос
/ 20 июня 2020

Это будет работать, но совсем не оптимизировано:

var result2 = result
    .GroupBy(i => new {i.GId, i.Share, i.Type, i.OPC, i.IPC})
    .Select(i1 => i1.LastOrDefault(i2 => i1.Count(i3 => i3.Price == i2.Price) == 1))
    .ToList();

Будет возвращена строка с идентификаторами «8131368» и «8131377»

Edit This код работает, но запрашивает вложенный l oop, которого можно избежать. Проверьте ответ Саджида с моим комментарием: -)

0 голосов
/ 20 июня 2020

Итак, мне нужно получить этот список или свойство Id из элемента списка, цена которого отличается, а остальные значения одинаковы.

Вы можете сгруппировать по значению кортеж, содержащий свойства, которые должны быть равно, а затем выберите группы с более чем одним элементом:

var itemIds = result
    .GroupBy(r => (r.GId, r.Share, r.Type, r.IPC, r.OPC))
    .Where(g => g.Select(r => r.Price).Distinct().Count() > 1) // or Count() == 2, then next clause can be simplified
    .Select(g => 
    {
        var byPrice = g.GroupBy(r => r.Price).ToList();
        
        if(byPrice.Count > 2)
        {
            throw new Exception("Could not determine base price - more than 2 groups");
        }
        
        if (byPrice.All(gg => gg.Count() == 1))
        {
            throw new Exception("Could not determine base price - multiple groups with single element");
        }
        
        return byPrice.First(gg => gg.Count() == 1).Select(r => r.Id).First();
    })
    .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...