【问题标题】:Selecting Ids in from source list by other comparing another property against different list通过其他将另一个属性与不同列表进行比较来从源列表中选择 ID
【发布时间】:2019-05-20 21:18:02
【问题描述】:

我有两个 Lists 的项目类对象,例如;

源列表

Id  DateTime
1   21.05.2019 10:00:00
2   21.05.2019 10:10:00
3   21.05.2019 10:20:00
4   21.05.2019 10:30:00
5   21.05.2019 10:40:00
6   21.05.2019 10:50:00
7   21.05.2019 11:00:00

目的地列表

Id  DateTime
1   21.05.2019 9:00:00
3   21.05.2019 10:25:00
5   21.05.2019 10:45:00
7   21.05.2019 10:30:00
9   21.05.2019 10:40:00
11  21.05.2019 10:50:00

我会从SourceList 中选择Ids 来查找两者:

  • 一个。 Ids 存在于 SourceList 但不存在 DestinationList (更不用说这个本身很容易)
  • 乙。 Ids 存在于两个列表中,但仅检索 SourceList 上较大的日期时间

所以示例结果将是 union of;

a. 2,4,6
b. 1,7

2,4,6,1,7

使用 lambda 表达式获得此结果的最有效方法是什么。

谢谢,

【问题讨论】:

  • 到目前为止你尝试了什么?

标签: c# generics lambda generic-list


【解决方案1】:
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var source = new[]
            {
                new Entry { Id = 1, DateTime = DateTime.Parse("21.05.2019 10:00:00") },
                new Entry { Id = 2, DateTime = DateTime.Parse("21.05.2019 10:10:00") },
                new Entry { Id = 3, DateTime = DateTime.Parse("21.05.2019 10:20:00") },
                new Entry { Id = 4, DateTime = DateTime.Parse("21.05.2019 10:30:00") },
                new Entry { Id = 5, DateTime = DateTime.Parse("21.05.2019 10:40:00") },
                new Entry { Id = 6, DateTime = DateTime.Parse("21.05.2019 10:50:00") },
                new Entry { Id = 7, DateTime = DateTime.Parse("21.05.2019 11:00:00") }
            };

            var destination = new[]
            {
                new Entry { Id = 1, DateTime = DateTime.Parse("21.05.2019 09:00:00") },
                new Entry { Id = 3, DateTime = DateTime.Parse("21.05.2019 10:25:00") },
                new Entry { Id = 5, DateTime = DateTime.Parse("21.05.2019 10:45:00") },
                new Entry { Id = 7, DateTime = DateTime.Parse("21.05.2019 10:30:00") },
                new Entry { Id = 9, DateTime = DateTime.Parse("21.05.2019 10:40:00") },
                new Entry { Id = 11, DateTime = DateTime.Parse("21.05.2019 10:50:00") }
            };

            var comparer = new EntryComparer();
            var partA = source.Except(destination, comparer);
            var partB = source.Intersect(destination, comparer)
                              .Where(i => source.First(j => j.Id == i.Id).DateTime >
                                          destination.First(j => j.Id == i.Id).DateTime);
            var result = partA.Concat(partB);
            foreach (var i in result)
                Console.WriteLine(i);
        }

        private class Entry
        {
            public int Id { get; set; }
            public DateTime DateTime { get; set; }

            public override string ToString() => $"{Id} {DateTime}";
        }

        private class EntryComparer : IEqualityComparer<Entry>
        {
            public bool Equals(Entry x, Entry y) => x.Id.Equals(y.Id);

            public int GetHashCode(Entry obj) => obj.Id.GetHashCode();
        }
    }
}

输出:

2 21.05.2019 10:10:00
4 21.05.2019 10:30:00
6 21.05.2019 10:50:00
1 21.05.2019 10:00:00
7 21.05.2019 11:00:00

【讨论】:

    【解决方案2】:

    有几种方法。一种是编写自己的EqualityComparator 并使用ExceptIntersect 列出结果,如上述结果中@Alex 所示,这是可靠的代码并且也可重用,但是如果你是寻找快速结果,您可以使用whereany 和/或两者的组合使用以下内容。

    所以要获得结果,linq 查询如下

    a) var resultWhereIdsExistsInSourceListButNotOnDestination = sourceList
    .Where(l1 => !destinationList.Any(l2 => l2.Id == l1.Id))
    .Select(l => l.Id);
    
    b) var resultWhereIdsExistInBothWithDateGreaterInSourceList =
     sourceList
    .Where(l1 => destinationList.Any(l2 => l2.Id == l1.Id && l1.Date > l2.Date))
    .Select(l => l.Id);
    
    c) var combinedResult = resultWhereIdsExistsInSourceListButNotOnDestination
       .Union(resultWhereIdsExistInBothWithDateGreaterInSourceList);
    

    小提琴链接https://dotnetfiddle.net/AGwFlC#

    注意:我使用了自己的样本数据。也只是为了使用ForEach 的可读性,我使用.ToList() 进行演示。不需要每次都将可枚举转换为列表。纯粹用于演示目的

            using System;
            using System.Collections.Generic;
            using System.Linq;
    
            public class Program
            {
                public static void Main()
                {
                    var sourceList = new List<Foo>()
                    {new Foo()
                    {Id = 1, Date = DateTime.Now}, new Foo()
                    {Id = 2, Date = DateTime.Now.AddDays(5)}, new Foo()
                    {Id = 3, Date = DateTime.Now.AddDays(3)}, new Foo()
                    {Id = 4, Date = DateTime.Now}, new Foo()
                    {Id = 5, Date = DateTime.Now}};
                    var destinationList = new List<Foo>()
                    {new Foo()
                    {Id = 2, Date = DateTime.Now}, new Foo()
                    {Id = 3, Date = DateTime.Now}, new Foo()
                    {Id = 4, Date = DateTime.Now}, new Foo()
                    };
    
                    Console.WriteLine("--IDs IN SOURCE LIST BUT NOT IN DESTINATION--------");
                    var resultWhereIdsExistsInSourceListButNotOnDestination = 
    sourceList
    .Where(l1 => !destinationList.Any(l2 => l2.Id == l1.Id)).Select(l => l.Id).ToList();
                    resultWhereIdsExistsInSourceListButNotOnDestination.ForEach(r => Console.WriteLine(r));
                    Console.WriteLine("--IDs IN BOTH WHERE THE DATE IN SOURCE LIST IS GREATER--------");
                    var resultWhereIdsExistInBothWithDateGreaterInSourceList = sourceList
        .Where(l1 => destinationList.Any(l2 => l2.Id == l1.Id && l1.Date > l2.Date)).Select(l => l.Id).ToList();
                    resultWhereIdsExistInBothWithDateGreaterInSourceList.ForEach(r => Console.WriteLine(r));
    
                    Console.WriteLine("------------------ UNINON-------------------------------------");
                    resultWhereIdsExistsInSourceListButNotOnDestination
        .Union(resultWhereIdsExistInBothWithDateGreaterInSourceList).ToList().ForEach(r => Console.WriteLine(r));
    
    
                }
            }
    
            public class Foo
            {
                public DateTime Date
                {
                    get;
                    set;
                }
    
                public int Id
                {
                    get;
                    set;
                }
            }
    
            ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 2020-07-30
      • 1970-01-01
      相关资源
      最近更新 更多