Фильтрация списков с помощью 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
}
}
Ответ 5
Вы можете использовать метод расширения "Исключить" (см. http://msdn.microsoft.com/en-us/library/bb337804.aspx)
В вашем коде
var difference = people.Except(exclusions);
Ответ 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);
});