Reputation: 4345
i have a two list
List<Sent> SentList;
List<Messages> MsgList;
both have the same property called MsgID;
MsgList SentList
MsgID Content MsgID Content Stauts
1 aaa 1 aaa 0
2 bbb 3 ccc 0
3 ccc
4 ddd
5 eee
i want to compare the MsgID in Msglist with the sentlist and need items which are not in the sent list using linq
Result
MsgID Content
2 bbb
4 ddd
5 eee
Upvotes: 46
Views: 160660
Reputation: 1
Make a single list:
var result = list.GroupBy(x => x.BillId).Where(x => x.Count() == 1).Select(x => x.First());
Upvotes: 0
Reputation: 2872
In .NET 6 you can take advantage of .ExceptBy()
, which lets you define which property of the first list to compare the items in the second list by:
List<Message> result = messages
.ExceptBy(sentList.Select(msg => msg.MsgID), msg => msg.MsgID)
.ToList();
messages
is the first list, whereas a collection of the MsgID
properties from sentList
is the second list.
Example fiddle here.
Note:
.ExceptBy()
produces the set difference between the two collections --> only distinct values will be in the resulting collection. This means that if messages
contains the same value more than once (e.g. { "aaa", "bbb", "ccc", "ddd", "ddd", "eee" }
), any duplicates will be removed in the resulting collection (--> { "bbb", "ddd", "eee" }
).
Upvotes: 6
Reputation: 21
If u wanna Select items of List from 2nd list:
MainList.Where(p => 2ndlist.Contains(p.columns from MainList )).ToList();
Upvotes: 0
Reputation: 642
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();
Person class
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
Upvotes: 0
Reputation: 2765
As an extension method
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);
}
eg.
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);
Upvotes: 0
Reputation: 3407
You can do like this,this is the quickest process
Var result = MsgList.Except(MsgList.Where(o => SentList.Select(s => s.MsgID).ToList().Contains(o.MsgID))).ToList();
This will give you expected output.
Upvotes: 10
Reputation: 3698
Try,
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>();
Hope it should help.
Upvotes: 3
Reputation: 116498
The naive approach:
MsgList.Where(x => !SentList.Any(y => y.MsgID == x.MsgID))
Be aware this will take up to m*n
operations as it compares every MsgID
in SentList
to each in MsgList
("up to" because it will short-circuit when it does happen to match).
Upvotes: 35
Reputation: 7692
Well, you already have good answers, but they're most Lambda. A more LINQ approach would be like
var NotSentMessages =
from msg in MsgList
where !SentList.Any(x => x.MsgID == msg.MsgID)
select msg;
Upvotes: 21
Reputation: 3610
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;
}
Upvotes: -1
Reputation: 150108
You can do something like
var notSent = MsgSent.Except(MsgList, MsgIdEqualityComparer);
You will need to provide a custom equality comparer as outlined on MSDN
http://msdn.microsoft.com/en-us/library/bb336390.aspx
Simply have that equality comparer base equality only on MsgID property of each respective type. Since the equality comparer compares two instances of the same type, you would need to define an interface or common base type that both Sent and Messages implement that has a MsgID property.
Upvotes: 9
Reputation: 564433
You could do something like:
HashSet<int> sentIDs = new HashSet<int>(SentList.Select(s => s.MsgID));
var results = MsgList.Where(m => !sentIDs.Contains(m.MsgID));
This will return all messages in MsgList
which don't have a matching ID in SentList
.
Upvotes: 56