C#在包含另一个列表的对象列表中查找重复的属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#在包含另一个列表的对象列表中查找重复的属性相关的知识,希望对你有一定的参考价值。

我有一个对象列表,让我们调用对象People。每个人都有他们要求的休假日列表。我正在尝试创建一个Linq查询,以了解有多少人请求了相同的休假日。我没有运气。任何建议,或者可能是正确方向的推动?

答案

你可以创建这样的类:

public class Person
{
    public List<int> Vacations { get; set; }
    public string Name { get; set; }
}

public class Vacation
{
    public List<string> People { get; set; }
    public int Day { get; set; }
    public int PeopleCount => People?.Count ?? 0;    
}

然后获取每天预订的人员列表,如下所示:

public void Test()
{
    var people = new List<Person>()
    {
        new Person() { Name = "Person1", Vacations = new List<int>() { 1, 15, 200, 364 } },
        new Person() { Name = "Person2", Vacations = new List<int>() { 1, 15, 110, 210 } },
        new Person() { Name = "Person3", Vacations = new List<int>() { 1, 15, 200 , 210} }
    };

    var vacations =
        Enumerable.Range(0, 365)
        .Select(d => new Vacation()
        {
            Day = d,
            People = people.Where(p
                => p.Vacations.Contains(d)).Select(p => p.Name).ToList()
        })
        .ToList();
}
另一答案

这应该有所帮助:

    class Customer
    {
        List<Vacation> vacationDays {get; set;}
    }

    public class Vacation : IEquatable<Vacation>
    {
        public string Name { get; set; }
        public int VacationId { get; set; }

        public override string ToString()
        {
            return "ID: " + VacationId + "   Name: " + Name;
        }
        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            Vacation objAsVacation = obj as Vacation;
            if (objAsVacation == null) return false;
            else return Equals(objAsVacation);
        }
        public override int GetHashCode()
        {
            return VacationId;
        }
        public bool Equals(Vacation other)
        {
            if (other == null) return false;
            return (this.VacationId.Equals(other.VacationId));
        }
        // Should also override == and != operators.
    }

现在,你可以在这里使用SelectMany

https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.selectmany?view=netframework-4.7.2

更多关于Contains的信息:

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.contains?view=netframework-4.7.2

另一答案

首先展平列表。此代码将创建一个单独的非嵌套列表,其中包含每个人/日期的一行:

var flatList = people.SelectMany
(
    p => p.VacationDays.Select( d => new { Person = p, Date = d } )
);

然后,您可以轻松过滤任何您想要的方式:

var lookFor = DateTime.Parse("1/1/2019");
var entriesForJan01 = flatList.Where( f => f.Date == lookFor );

单击此链接以获取working example on DotNetFiddle

另一答案

这可以通过LINQ以多种方式完成,但如果您想要查找多个日期,我想建议一个更有效的解决方案。我的解决方案使用Dictionary<DateTime,int>作为我们遇到的日子的计数器。由于Dictionary查找具有恒定的时间复杂度(O(1)),当您需要检查多个日期甚至所有日期的出现次数时,此解决方案将非常有效。

var dateOccurrences = new Dictionary<DateTime, int>();
foreach (var vacationDate in people.SelectMany(p => p.Vacations))
{
    //check if we already have this date in the dictionary
    if (!dateOccurrences.TryGetValue(vacationDate.Date, out int previousOccurrences))
    {
        //never seen before
        previousOccurrences = 0;                    
    }
    //add one occurrence
    dateOccurrences[vacationDate] = previousOccurrences + 1;
}

现在查找只需再次使用TryGetValue。或者,您可以在所有字典条目上使用foreach

foreach (var pair in dateOccurrences)
{
    Console.WriteLine(pair.Key);
    Console.WriteLine(pair.Value);
}

以上是关于C#在包含另一个列表的对象列表中查找重复的属性的主要内容,如果未能解决你的问题,请参考以下文章

查找一个列表中具有与另一个对象列表中的属性匹配的属性的所有对象

Grails:查找具有列表属性的对象,其中包含具有给定属性值的对象

C# - 将一个类的列表转换为具有相同属性的另一个类的列表[重复]

如何从对象数组中获取具有属性的列表,除非它包含具有特定值的另一个项目?

从一个列表中删除元素如果不包含在另一个列表中。 C# [重复]

查找重复的书籍