Выбор идентификаторов в списке источников путем сравнения другого свойства с другим списком - PullRequest
2 голосов
/ 21 мая 2019

У меня есть два List объекта классов предметов, таких как;

SOURCELIST

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

DESTINATIONLIST

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

Я бы выбрал Id s из SourceList, чтобы найти оба:

  • а. Id с, которые существуют на SourceList, но не существуют DestinationList (не говоря уже о том, что это легко само по себе)
  • б. Id с, которые существуют в обоих списках, но извлекают только те, чья дата и время больше SourceList

Таким образом, результатом примера будет объединение;

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

2,4,6,1,7

Как наиболее эффективно получить этот результат, используя лямбда-выражения.

Спасибо,

Ответы [ 2 ]

1 голос
/ 21 мая 2019

Есть несколько способов.Один из них - написать свой EqualityComparator и перечислить результат, используя Except и Intersect, как показано @Alex в приведенном выше результате, который представляет собой твердый код и также может использоваться повторно , однако, если вы ищетедля быстрых результатов вы можете использовать следующее, используя where и any или их комбинации.

Таким образом, чтобы получить результаты, запросы 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);

Ссылка Fiddle : 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;
            }
        }

        ;
1 голос
/ 21 мая 2019
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
...