Фильтрация списков с помощью LINQ

У меня есть список людей, которые возвращаются из внешнего приложения, и я создаю список исключений в своем локальном приложении, чтобы дать мне возможность вручную удалять людей из списка.

У меня есть составной ключ, который я создал, который является общим для обоих, и я хочу найти эффективный способ удаления людей из моего списка с помощью моего списка

e.g

class Person
{
    prop string compositeKey { get; set; }
}

class Exclusions
{
    prop string compositeKey { get; set; }
}

List<Person> people = GetFromDB;

List<Exclusions> exclusions = GetFromOtherDB;

List<Person> filteredResults = People - exclustions using the composite key as a comparer

Я думал, что LINQ - идеальный способ сделать это, но после попытки объединения, методов расширения, использования доходностей и т.д. У меня все еще возникают проблемы.

Если бы это был SQL, я бы использовал запрос not in (?,?,?).

Ответы

Ответ 1

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

var resultingList = 
    listOfOriginalItems.Except(listOfItemsToLeaveOut, equalityComparer)

Вы хотите использовать перегрузку, с которой я связан, что позволяет указать пользовательский IEqualityComparer. Таким образом вы можете указать, как элементы соответствуют на основе вашего составного ключа. (Если вы уже переопределили Equals, вам не нужен IEqualityComparer.)

Изменить:. Похоже, вы используете два разных типа классов, здесь другой способ, который может быть проще. Предполагая, что List<Person> называется persons и a List<Exclusion> называется exclusions:

var exclusionKeys = 
        exclusions.Select(x => x.compositeKey);
var resultingPersons = 
        persons.Where(x => !exclusionKeys.Contains(x.compositeKey));

Другими словами: выберите из исключений только ключи, а затем выберите из всех объектов Person, у которых нет этих ключей.

Ответ 2

Я бы просто использовал метод FindAll в классе List. то есть:.

List<Person> filteredResults = 
    people.FindAll(p => return !exclusions.Contains(p));

Не уверен, что синтаксис будет точно соответствовать вашим объектам, но я думаю, вы можете увидеть, где я собираюсь с этим.

Ответ 3

Большое спасибо за этих парней.

Мне удалось перевести это в одну строку:

  var results = from p in People 
                where !(from e in exclusions 
                        select e.CompositeKey).Contains(p.CompositeKey) 
                select p;

Еще раз спасибо всем.

Ответ 4

Я не мог понять, как это сделать в чистой MS LINQ, поэтому я написал свой собственный метод расширения для этого:

public static bool In<T>(this T objToCheck, params T[] values)
{
    if (values == null || values.Length == 0) 
    {
        return false; //early out
    }
    else
    {
        foreach (T t in values)
        {
            if (t.Equals(objToCheck))
                return true;   //RETURN found!
        }

        return false; //nothing found
    }
}

Ответ 6

Я бы сделал что-то подобное, но я уверен, что есть более простой способ. я думаю, что sql из linqtosql будет использовать выбор из человека, где НЕ СУЩЕСТВУЕТ (выберите из списка исключений)

static class Program
{
    public class Person
    {
        public string Key { get; set; }
        public Person(string key)
        {
           Key = key;
        }
    }
    public class NotPerson
    {
        public string Key { get; set; }
        public NotPerson(string key)
        {
           Key = key;
        }
    }
    static void Main()
    {

       List<Person> persons = new List<Person>()
       { 
           new Person ("1"),
           new Person ("2"),
           new Person ("3"),
           new Person ("4")
       };

       List<NotPerson> notpersons = new List<NotPerson>()
       { 
           new NotPerson ("3"),
           new NotPerson ("4")
       };

       var filteredResults = from n in persons
                             where !notpersons.Any(y => n.Key == y.Key)
                             select n;

       foreach (var item in filteredResults)
       {
          Console.WriteLine(item.Key);
       }
    }
 }

Ответ 7

В этом LINQ ниже будет генерироваться SQL для левого внешнего соединения, а затем взять все результаты, которые не найдут совпадение в вашем списке исключений.

List<Person> filteredResults =from p in people
        join e in exclusions on p.compositeKey equals e.compositeKey into temp
        from t in temp.DefaultIfEmpty()
        where t.compositeKey == null
        select p

сообщите мне, если он работает!

Ответ 8

            var result = Data.Where(x =>
            {
            bool condition = true;
            double accord = (double)x[Table.Columns.IndexOf(FiltercomboBox.Text)];
            return condition && accord >= double.Parse(FilterLowertextBox.Text) && accord <= double.Parse(FilterUppertextBox.Text); 
        });