2012-08-14 18 views
17

का उपयोग कर आइटम मिलान नहीं वापसी मैं एक दो सूचीदो सूची की तुलना और LINQ

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

दोनों एक ही संपत्ति msgId कहा जाता है है;

MsgList   SentList 

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

मैं sentlist साथ Msglist में msgId तुलना करना चाहते हैं और आइटम LINQ

Result 

MsgID Content 
2  bbb 
4  ddd 
5  eee 
+3

न भूलें * सही चिह्नित करने के लिए * जवाब यह है कि आप अपनी समस्या =) –

उत्तर

12

का उपयोग कर अनुभवहीन दृष्टिकोण है जो भेजा सूची में नहीं हैं की जरूरत है:

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

ध्यान रखें इसमें m*n संचालन होंगे क्योंकि यह प्रत्येक MsgIDSentList में MsgList ("तक" में प्रत्येक के लिए तुलना करता है क्योंकि यह शॉर्ट-सर्किट होगा टी मैच के साथ होता है)।

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

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

यह MsgList में सभी संदेशों को वापस आ जाएगी जो SentList में मेल खाने वाले आईडी नहीं है:

+2

के साथ मदद आप downvote के लिए जा रहे हैं, तो आप कम से कम मुझे क्यों समझाने का आम शिष्टाचार कर सकता है। –

+0

कैसे करें: 'MsgList.Where (x => SentList.All (y => y.MsgID == x.MsgID)) ' – zumalifeguard

+0

@ ज़ूमलिफ़गार्ड मुझे लगता है कि आपका मतलब है'! =' और यदि हां, तो यह तर्कसंगत समकक्ष अभिव्यक्ति है जो एक ही समय लेना चाहिए। –

23

आप की तरह कुछ कर सकता है।

+1

यह शायद सबसे अच्छा तरीका –

8

के रूप में MSDN

पर उल्लिखित

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

सीधे शब्दों में केवल के msgId संपत्ति पर है कि समानता comparer आधार समानता है तो आप की तरह

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

आप एक कस्टम समानता comparer प्रदान करना होगा कुछ कर सकते हैं प्रत्येक संबंधित प्रकार। के बाद से समानता comparer एक ही प्रकार के दो उदाहरणों तुलना, आप को लागू है कि एक 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

आह है, वास्तव में एलसी के समान समाधान। की तैनाती। लेकिन, ठीक है, यहां आपके पास पूर्ण और परीक्षण किए गए उदाहरण हैं। – Tys

11

ठीक है, आपके पास पहले से ही अच्छे उत्तर हैं, लेकिन वे सबसे अधिक Lambda हैं। एक और अधिक LINQ दृष्टिकोण की तरह

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

'वर NotSentMessages = संदेश से MsgList में जहां SentList.Any (x => x.MsgID == msg.MsgID && x.content == msg.content) चयन संदेश!' इस तुलना के लिए बेहतर है एकाधिक गुणों (संयुक्त कुंजी) –

+0

@AndrewDay हाँ लेकिन ओपी ने कहा कि वह बराबर आईडी जांचना चाहता था, इसलिए तारों से मिलान करने की कोई आवश्यकता नहीं है। –

+0

- इसलिए आपका कोड बेहतर कोड है क्योंकि यह विस्तार योग्य है। लेकिन यह एक बुरी टिप्पणी ???? –

2

प्रयास होगा,

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

आशा है कि यह मदद करनी चाहिए।

3

आप इस तरह से कर सकते हैं, इस तेज प्रक्रिया

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

यह आपको उत्पादन की उम्मीद दे देंगे।

0

एक विस्तार विधि

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

जैसे के रूप में।

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); 
संबंधित मुद्दे