wake-up-neo.com

vergleichen Sie zwei Listen und geben Sie mit linq nicht übereinstimmende Elemente zurück

ich habe eine Liste mit zwei

List<Sent> SentList;
List<Messages> MsgList;

beide haben die gleiche Eigenschaft namens MsgID;

MsgList            SentList  

MsgID Content      MsgID Content Stauts
1       aaa        1       aaa     0
2       bbb        3       ccc     0
3       ccc        
4       ddd
5       eee

ich möchte die MsgID in Msglist mit der Sendeliste vergleichen und benötige Elemente, die nicht in der gesendeten Liste mit Linq enthalten sind

Result 

MsgID Content
2       bbb
4       ddd
5       eee
20
Spen D

Sie könnten so etwas tun:

HashSet<int> sentIDs = new HashSet<int>(SentList.Select(s => s.MsgID));

var results = MsgList.Where(m => !sentIDs.Contains(m.MsgID));

Dadurch werden alle Nachrichten in MsgList zurückgegeben, für die keine passende ID in SentList vorhanden ist.

28
Reed Copsey

Der naive Ansatz:

MsgList.Where(x => !SentList.Any(y => y.MsgID == x.MsgID))

Beachten Sie, dass dies m*n-Vorgänge erfordert, da es jede MsgID in SentList mit jeder in MsgList vergleicht ("bis zu", da dies einen Kurzschluss verursachen wird, wenn stimmt zufällig zusammen passt).

14
lc.

Nun, Sie haben bereits gute Antworten, aber das sind die meisten Lambda. Ein mehr LINQ-Ansatz wäre ähnlich

var NotSentMessages =
                from msg in MsgList
                where !SentList.Any(x => x.MsgID == msg.MsgID)
                select msg;
11
Andre Calil

Sie können so etwas tun

var notSent = MsgSent.Except(MsgList, MsgIdEqualityComparer);

Sie müssen einen benutzerdefinierten Gleichheitsvergleicher bereitstellen, wie in MSDN beschrieben

http://msdn.Microsoft.com/de-de/library/bb336390.aspx

Die Basisgleichheit für den Gleichheitsvergleicher muss nur für die MsgID-Eigenschaft des jeweiligen Typs gelten. Da der Gleichheitsvergleicher zwei Instanzen desselben Typs vergleicht, müssten Sie eine Schnittstelle oder einen allgemeinen Basistyp definieren, die sowohl Sent als auch Messages implementieren und eine MsgID - Eigenschaft besitzen.

8
Eric J.

Das können Sie so machen, das ist der schnellste Prozess

Var result = MsgList.Except(MsgList.Where(o => SentList.Select(s => s.MsgID).ToList().Contains(o.MsgID))).ToList();

Dadurch erhalten Sie die erwartete Ausgabe.

4
Tushar patel

Versuchen,

  public class Sent
{
    public int MsgID;
    public string Content;
    public int Status;

}

public class Messages
{
    public int MsgID;
    public string Content;
}

  List<Sent> SentList = new List<Sent>() { new Sent() { MsgID = 1, Content = "aaa", Status = 0 }, new Sent() { MsgID = 3, Content = "ccc", Status = 0 } };
            List<Messages> MsgList = new List<Messages>() { new Messages() { MsgID = 1, Content = "aaa" }, new Messages() { MsgID = 2, Content = "bbb" }, new Messages() { MsgID = 3, Content = "ccc" }, new Messages() { MsgID = 4, Content = "ddd" }, new Messages() { MsgID = 5, Content = "eee" }};

            int [] sentMsgIDs = SentList.Select(v => v.MsgID).ToArray();
            List<Messages> result1 = MsgList.Where(o => !sentMsgIDs.Contains(o.MsgID)).ToList<Messages>();

Ich hoffe es sollte helfen.

2
Jignesh Thakker
List<Car> cars = new List<Car>() {  new Car() { Name = "Ford", Year = 1892, Website = "www.ford.us" }, 
                                    new Car() { Name = "Jaguar", Year = 1892, Website = "www.jaguar.co.uk" }, 
                                    new Car() { Name = "Honda", Year = 1892, Website = "www.honda.jp"} };

List<Factory> factories = new List<Factory>() {     new Factory() { Name = "Ferrari", Website = "www.ferrari.it" }, 
                                                    new Factory() { Name = "Jaguar", Website = "www.jaguar.co.uk" }, 
                                                    new Factory() { Name = "BMW", Website = "www.bmw.de"} };

foreach (Car car in cars.Where(c => !factories.Any(f => f.Name == c.Name))) {
    lblDebug.Text += car.Name;
}
0
Tys
List<Person> persons1 = new List<Person>
           {
                    new Person {Id = 1, Name = "Person 1"},
                    new Person {Id = 2, Name = "Person 2"},
                    new Person {Id = 3, Name = "Person 3"},
                    new Person {Id = 4, Name = "Person 4"}
           };


        List<Person> persons2 = new List<Person>
           {
                    new Person {Id = 1, Name = "Person 1"},
                    new Person {Id = 2, Name = "Person 2"},
                    new Person {Id = 3, Name = "Person 3"},
                    new Person {Id = 4, Name = "Person 4"},
                    new Person {Id = 5, Name = "Person 5"},
                    new Person {Id = 6, Name = "Person 6"},
                    new Person {Id = 7, Name = "Person 7"}
           };
        var output = (from ps1 in persons1
                      from ps2 in persons2
                      where ps1.Id == ps2.Id
                      select ps2.Name).ToList();

Personenklasse

public class Person
{        
    public int Id { get; set; }       

    public string Name { get; set; }
}
0
Sapnandu

Als Erweiterungsmethode

public static IEnumerable<TSource> AreNotEqual<TSource, TKey, TTarget>(this IEnumerable<TSource> source, Func<TSource, TKey> sourceKeySelector, IEnumerable<TTarget> target, Func<TTarget, TKey> targetKeySelector) 
{
    var targetValues = new HashSet<TKey>(target.Select(targetKeySelector));

    return source.Where(sourceValue => targetValues.Contains(sourceKeySelector(sourceValue)) == false);
}

z.B.

public class Customer
{
    public int CustomerId { get; set; }
}

public class OtherCustomer
{
    public int Id { get; set; }
}


var customers = new List<Customer>()
{
    new Customer() { CustomerId = 1 },
    new Customer() { CustomerId = 2 }
};

var others = new List<OtherCustomer>()
{
    new OtherCustomer() { Id = 2 },
    new OtherCustomer() { Id = 3 }
};

var result = customers.AreNotEqual(customer => customer.CustomerId, others, other => other.Id).ToList();

Debug.Assert(result.Count == 1);
Debug.Assert(result[0].CustomerId == 1);
0
Matt Searles