2012-08-14 35 views
17

tôi có một danh sách haiso sánh hai danh sách và gửi lại không phù hợp với mục sử dụng LINQ

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

cả hai đều có tính chất gọi là msgstr cùng;

MsgList   SentList 

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

tôi muốn so sánh các msgstr trong Msglist với sentlist và cần các mục mà không có trong danh sách được gửi bằng LINQ

Result 

MsgID Content 
2  bbb 
4  ddd 
5  eee 
+3

Đừng quên đánh dấu là * chính xác * câu trả lời giúp bạn giải quyết vấn đề =) –

Trả lời

12

Cách tiếp cận ngây thơ:

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

Hãy nhận biết điều này sẽ mất đến m*n hoạt động vì nó so sánh mỗi MsgID trong SentList cho mỗi trong MsgList ("tối đa" vì nó sẽ ngắn mạch khi tôi t hiện xảy ra để khớp).

+2

Nếu bạn sắp downvote, ít nhất bạn cũng có thể giải thích lý do tại sao. –

+0

Làm thế nào về: 'MsgList.Where (x => SentList.All (y => y.MsgID == x.MsgID))' – zumalifeguard

+0

@zumalifeguard Tôi đoán bạn có nghĩa là '! =' Và nếu có thì đó là một biểu thức tương đương logic nên dùng cùng một lượng thời gian. –

23

Bạn có thể làm một cái gì đó như:

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

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

này sẽ trả lại tất cả thư trong MsgList mà không có một ID tương ứng trong SentList.

+1

Đây có lẽ là cách tiếp cận tốt nhất –

8

Bạn có thể làm một cái gì đó giống như

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

Bạn sẽ cần phải cung cấp một comparer bình đẳng tùy chỉnh như đã nêu trên MSDN

http://msdn.microsoft.com/en-us/library/bb336390.aspx

Đơn giản chỉ cần có mà bình đẳng bình đẳng Comparer cơ sở duy nhất về sở hữu của msgstr từng loại tương ứng. Vì trình so sánh bình đẳng so sánh hai trường hợp cùng loại, bạn cần phải xác định giao diện hoặc loại cơ sở chung mà cả Đã gửiThông báo triển khai có thuộc tính MsgID.

0
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

Ah, chính xác giải pháp tương tự như lc. đã đăng. Nhưng, tốt, ở đây bạn có nó với một ví dụ đầy đủ và thử nghiệm. – Tys

11

Vâng, bạn đã có câu trả lời hay nhưng chúng là Lambda nhất. Một cách tiếp cận LINQ hơn sẽ như thế nào

var NotSentMessages = 
       from msg in MsgList 
       where !SentList.Any(x => x.MsgID == msg.MsgID) 
       select msg; 
+0

'var NotSentMessages = từ msg trong MsgList nơi SentList.Any (x => x.MsgID == msg.MsgID && x.content == msg.content) chọn msg;!' này là tốt hơn để so sánh nhiều thuộc tính (các phím kết hợp) –

+0

@AndrewDay nhưng OP cho biết anh muốn kiểm tra các ID bằng nhau, vì vậy không cần phải khớp các chuỗi ở đây. –

+0

- vì vậy mã của bạn là mã tốt hơn vì nó có thể mở rộng. Nhưng đó là một bình luận xấu ???? –

2

Cố gắng,

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>(); 

Hy vọng nó sẽ giúp.

3

Bạn có thể làm như thế này, đây là một quá trình nhanh nhất

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

này sẽ cung cấp cho bạn dự kiến ​​sản lượng.

0

Là một phương pháp khuyến nông

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); 
} 

ví dụ.

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); 
Các vấn đề liên quan