Jak zrobić zapytanie "Nie w" z LINQ?
Mam dwa zbiory, które mają własność Email
w obu zbiorach. Muszę uzyskać listę elementów z pierwszej listy, gdzie Email
nie istnieje na drugiej liście. W SQL użyłbym tylko "not in", ale nie znam odpowiednika w LINQ. Jak to się robi?
var matches = from item1 in list1
join item2 in list2 on item1.Email equals item2.Email
select new { Email = list1.Email };
Ale nie mogę dołączyć, ponieważ potrzebuję różnicy, a połączenie zawiedzie. Potrzebuję jakiegoś sposobu na użycie zawartości lub istnieje, jak sądzę. Po prostu nie znalazłem przykładu do zrobienia to jeszcze.
15 answers
Nie wiem, czy to ci pomoże, ale ... .
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !(from o in dc.Orders
select o.CustomerID)
.Contains(c.CustomerID)
select c;
foreach (var c in query) Console.WriteLine( c );
From The NOT in clause in LINQ to SQL by
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-26 05:41:48
Chcesz operatora z wyjątkiem.
var answer = list1.Except(list2);
Lepsze wyjaśnienie tutaj: http://blogs.msdn.com/charlie/archive/2008/07/12/the-linq-set-operators.aspx
Uwaga: ta technika działa najlepiej tylko dla typów prymitywnych, ponieważ musisz zaimplementować IEqualityComparer aby użyć metody Except z typami złożonymi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 16:42:33
Pozycje na pierwszej liście, gdzie e-mail nie istnieje na drugiej liście.
from item1 in List1
where !(list2.Any(item2 => item2.Email == item1.Email))
select item1;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 17:50:41
Dla osób, które zaczynają od grupy obiektów w pamięci i pytają o bazę danych, uznałem to za najlepszy sposób:
var itemIds = inMemoryList.Select(x => x.Id).ToArray();
var otherObjects = context.ItemList.Where(x => !itemIds.Contains(x.Id));
To tworzy ładną klauzulę WHERE ... IN (...)
w SQL.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-05 15:21:42
Możesz użyć kombinacji Where I Any dla znalezienia Nie w:
var NotInRecord =list1.Where(p => !list2.Any(p2 => p2.Email == p.Email));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 20:33:05
Możesz wziąć oba zbiory w dwóch różnych listach, powiedzmy list1 i list2.
To po prostu napisz
list1.RemoveAll(Item => list2.Contains(Item));
To zadziała.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 20:29:58
W przypadku, gdy ktoś używa ADO.NET Entity Framework , rozwiązanie Echostorma również działa doskonale. Ale zajęło mi kilka minut, żeby to ogarnąć. Zakładając, że masz kontekst bazy danych, dc i chcesz znaleźć wiersze w tabeli x, które nie są połączone w tabeli y, pełna odpowiedź odpowiedzi wygląda następująco:
var linked =
from x in dc.X
from y in dc.Y
where x.MyProperty == y.MyProperty
select x;
var notLinked =
dc.X.Except(linked);
W odpowiedzi na komentarz Andy 'ego, tak, można mieć dwa from' y w zapytaniu LINQ. Oto kompletny przykład pracy, używając list. Każda klasa, Foo i Bar, ma identyfikator. Foo ma" klucz obcy " odniesienie do paska przez Foo.BarId. Program wybiera wszystkie Foo Nie powiązane z odpowiednim paskiem.
class Program
{
static void Main(string[] args)
{
// Creates some foos
List<Foo> fooList = new List<Foo>();
fooList.Add(new Foo { Id = 1, BarId = 11 });
fooList.Add(new Foo { Id = 2, BarId = 12 });
fooList.Add(new Foo { Id = 3, BarId = 13 });
fooList.Add(new Foo { Id = 4, BarId = 14 });
fooList.Add(new Foo { Id = 5, BarId = -1 });
fooList.Add(new Foo { Id = 6, BarId = -1 });
fooList.Add(new Foo { Id = 7, BarId = -1 });
// Create some bars
List<Bar> barList = new List<Bar>();
barList.Add(new Bar { Id = 11 });
barList.Add(new Bar { Id = 12 });
barList.Add(new Bar { Id = 13 });
barList.Add(new Bar { Id = 14 });
barList.Add(new Bar { Id = 15 });
barList.Add(new Bar { Id = 16 });
barList.Add(new Bar { Id = 17 });
var linked = from foo in fooList
from bar in barList
where foo.BarId == bar.Id
select foo;
var notLinked = fooList.Except(linked);
foreach (Foo item in notLinked)
{
Console.WriteLine(
String.Format(
"Foo.Id: {0} | Bar.Id: {1}",
item.Id, item.BarId));
}
Console.WriteLine("Any key to continue...");
Console.ReadKey();
}
}
class Foo
{
public int Id { get; set; }
public int BarId { get; set; }
}
class Bar
{
public int Id { get; set; }
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 20:27:40
var secondEmails = (from item in list2
select new { Email = item.Email }
).ToList();
var matches = from item in list1
where !secondEmails.Contains(item.Email)
select new {Email = item.Email};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 17:05:20
Podczas gdy Except
jest częścią odpowiedzi, nie jest to cała odpowiedź. Domyślnie, Except
(podobnie jak kilka operatorów LINQ) dokonuje porównania referencji na typach referencji. Aby porównać wartości w obiektach, musisz
- zaimplementuj
IEquatable<T>
w swoim typie, lub - override
Equals
andGetHashCode
in your type, or - pass in a instance of a type implementing
IEqualityComparer<T>
for your type
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 18:47:10
Przykład użycia listy int dla uproszczenia.
List<int> list1 = new List<int>();
// fill data
List<int> list2 = new List<int>();
// fill data
var results = from i in list1
where !list2.Contains(i)
select i;
foreach (var result in results)
Console.WriteLine(result.ToString());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 17:08:13
Dla każdego, kto również chce używać operatora SQL-alike IN
w C#, Pobierz ten pakiet:
Mshwf.NiceLinq
Ma metody In
i NotIn
:
var result = list1.In(x => x.Email, list2.Select(z => z.Email));
Nawet ty możesz użyć tego w ten sposób
var result = list1.In(x => x.Email, "[email protected]", "[email protected]", "[email protected]");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-12 12:13:43
Można też użyć All()
var notInList = list1.Where(p => list2.All(p2 => p2.Email != p.Email));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 08:52:00
Dziękuję, Brett. Twoja sugestia też mi pomogła. Miałem listę obiektów i chciałem filtrować ją za pomocą innej listy obiektów. Jeszcze raz dziękuję....
Jeśli ktoś potrzebuje, proszę spojrzeć na mój kod przykładowy:
'First, get all the items present in the local branch database
Dim _AllItems As List(Of LocalItem) = getAllItemsAtBranch(BranchId, RecordState.All)
'Then get the Item Mappings Present for the branch
Dim _adpt As New gItem_BranchesTableAdapter
Dim dt As New ds_CA_HO.gItem_BranchesDataTable
_adpt.FillBranchMappings(dt, BranchId)
Dim _MappedItems As List(Of LocalItem) = (From _item As LocalItem In _AllItems Join _
dr As ds_CA_HO.gItem_BranchesRow In dt _
On _item.Id Equals dr.numItemID _
Select _item).ToList
_AllItems = _AllItems.Except(_MappedItems.AsEnumerable).ToList
Return _AllItems
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 20:28:49
Nie testowałem tego z LINQ to Entities :
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !dc.Orders.Any(o => o.CustomerID == c.CustomerID)
select c;
Alternatywnie:
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where dc.Orders.All(o => o.CustomerID != c.CustomerID)
select c;
foreach (var c in query)
Console.WriteLine( c );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 20:32:13
Nie możesz wykonać zewnętrznego połączenia, wybierając tylko elementy z pierwszej listy, jeśli grupa jest pusta? Coś w stylu:
Dim result = (From a In list1
Group Join b In list2
On a.Value Equals b.Value
Into grp = Group
Where Not grp.Any
Select a)
Nie jestem pewien, czy to zadziała w jakikolwiek efektywny sposób z ramą encji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-23 11:33:09