Есть такой код.
Для упрощения в классе 3 поля.
Суть в том что один запрос идет в foreach просто по разным полям.
Как можно схлопнуть это чтобы был один foreach?
using System.Linq.Expressions;
namespace helloworld
{
class hello
{
static void Main()
{
var p1 = new Person() { Age = 3, Name = "vova" };
var p2 = new Person() { Age = 3, Name = "vova2" };
var p3 = new Person() { Age = 32, Name = "vova2" };
var p4 = new Person() { Age = 33, Name = "vova2" };
var p14 = new Person() { Age = 323, Name = "vova24" };
var list = new List<Person>() { p1, p2, p3, p4, p14 };
foreach (var p in list
.GroupBy(a => a.Id)
.Where(x => x.Select(a => a.Age)
.Distinct()
.Count() > 1
)
.SelectMany(s => s.Select(o => o)))
{
//log error by Age
}
foreach (var p in list
.GroupBy(a => a.Id)
.Where(x => x.Select(a => a.Name)
.Distinct()
.Count() > 1
)
.SelectMany(s => s.Select(o => o)))
{
//log error by Name
}
}
class Person
{
public int Id;
public string Name { get; set; }
public int Age { get; set; }
}
}
}
никак. тебе надо найти айтемы, имеющие более одного неуникального значения по какому то из уникальных атрибутов, верно? код очень тяжело передает твои намерения. гораздо читабельнее было бы завести словарь Dictionary<string, object> и один раз пробежаться по коллекции с проверкой значений уникальных атрибитов по тому словарю попутно заполняя словарь. Обрати внимание на важность спртировки. Твой подход дискредиторует линк как технологию, кто то может посмотреть на это все ужаснуться и больше никогда к нему не прикасаться.
на быструю примерно так, добавил ref.
namespace HelloWorld
{
class Hello
{
enum Attribute
{
Age, Name
}
static void Main()
{
var people = new List<Person>() {
new () { Id = 1, Age = 3, Name = "vova" },
new () { Id = 1, Age = 31, Name = "vova" },
new () { Id = 2, Age = 32, Name = "vova2" },
new () { Id = 2, Age = 33, Name = "vova2" },
new () { Id = 4, Age = 323, Name = "vova24" },
new () { Id = 4, Age = 323, Name = "vova25" }
};
List<(int, Attribute, object, object)> Validate(Person person, ref Dictionary<int, Dictionary<Attribute, object>> processedPeople)
{
object GetValue(Person person, Attribute attribute) =>
attribute switch
{
Attribute.Age => person.Age,
Attribute.Name => person.Name,
_ => throw new ArgumentException($"Invalid attribute: '{attribute}'"),
};
var errors = new List<(int, Attribute, object, object)>();
foreach (var attribute
in Enum.GetValues<Attribute>())
{
if (!processedPeople.TryGetValue(person.Id,
out var processedPerson))
{
processedPerson = new();
processedPeople.Add(person.Id, processedPerson);
}
if (!processedPerson.TryGetValue(attribute, out var originalValue))
{
originalValue = GetValue(person, attribute);
processedPerson.Add(attribute, originalValue);
}
else
{
var value = GetValue(person, attribute);
if (originalValue != value)
{
errors.Add(new(person.Id, attribute, value, originalValue));
}
}
}
return errors;
}
var processedPeople = new Dictionary<int, Dictionary<Attribute, object>>(); // note: mutable state
foreach ((int id, Attribute attribute, object value, object originalValue)
in people.SelectMany(person => Validate(person, ref processedPeople)))
{
Console.WriteLine($"Person Id: {id} '{attribute}' value specified ambiguously, value: '{value}', original value: '{originalValue}'");
}
Console.ReadLine();
}
class Person
{
public int Id;
public required string Name { get; set; }
public int Age { get; set; }
}
}
}
Здравствуйте, peer, Вы писали:
P>Как можно схлопнуть это чтобы был один foreach?
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace helloworld
{
class hello
{
static void Main()
{
var p1 = new Person() { Age = 3, Name = "vova" };
var p2 = new Person() { Age = 3, Name = "vova2" };
var p3 = new Person() { Age = 32, Name = "vova2" };
var p4 = new Person() { Age = 33, Name = "vova2" };
var p14 = new Person() { Age = 323, Name = "vova24" };
var list = new List<Person>() { p1, p2, p3, p4, p14 };
var g = list.GroupBy(a => a.Id);
var aa = g.Where(x => (x.Select(a => a.Age).Distinct().Count() > 1))
.SelectMany(s => s.Select(o => (id:o.Id, attr:"age")));
var an = g.Where(x => (x.Select(a => a.Name).Distinct().Count() > 1))
.SelectMany(s => s.Select(o => (id:o.Id, attr:"name")));
foreach (var e in aa.Union(an))
{
System.Console.WriteLine($"Group # {e.id} contains duplicates by {e.attr}");
}
}
class Person
{
public int Id;
public string Name { get; set; }
public int Age { get; set; }
}
}
}
?