2008-10-02 9 views
10

निम्न प्रकार की कल्पना कीजिए:सी # में दो IList सिंक्रनाइज़ करने के लिए सबसे अच्छा एल्गोरिथ्म 2.0

public struct Account 
{ 
    public int Id; 
    public double Amount; 
} 

सबसे अच्छा कलन विधि सी # 2.0 में दो IList<Account> सिंक्रनाइज़ करने के लिए क्या है? (कोई linq)?

  • एल 2 में सभी खातों को नहीं रह गया है एल 1 में मौजूद हैं हटा दिया जाना चाहिए:

    पहली सूची (एल 1) संदर्भ सूची, दूसरा (एल 2) पहले के अनुसार सिंक्रनाइज़ करने के लिए एक है एल 2 से

  • एल 2 में सभी खातों को अभी भी एल 1 में मौजूद अद्यतन किया जाना चाहिए (राशि विशेषता)
  • सभी खातों को एल 1 में हैं, लेकिन अभी तक नहीं एल 2 में एल 2

में जोड़ा जाना चाहिए आईडी एसीसी की पहचान करता है ounts। एक निष्पक्ष और काम करने वाले एल्गोरिदम को ढूंढना बहुत मुश्किल नहीं है, लेकिन मैं जानना चाहता हूं कि पठनीयता और perfs को बर्बाद किए बिना इस परिदृश्य को संभालने का कोई स्मार्ट समाधान है या नहीं।

संपादित:

  • खाता प्रकार कोई फर्क नहीं पड़ता, एक वर्ग हो सकता है गुण, समानता के सदस्यों, आदि है
  • L1 और L2 पृथक नहीं किया जा
  • एल 2 आइटम सका एल 1 आइटमों द्वारा प्रतिस्थापित नहीं किया जाना चाहिए, उन्हें अद्यतन किया जाना चाहिए (क्षेत्र द्वारा क्षेत्र, संपत्ति द्वारा संपत्ति)
+0

क्या कोई अच्छा कारण है कि आप केवल संदर्भ सूची की प्रतिलिपि नहीं बना सकते? एल 2 = एल 1; आपके द्वारा दिए गए मानदंडों के आधार पर आपको जो चाहिए उसे लगता है। –

+0

हां, एल 2 सूची एक बाध्यकारी सूची है जो ग्रिड के लिए डेटासोर्स के रूप में उपयोग की जाती है। एल 1 और एल 2 ऑब्जेक्ट्स एक ही प्रकार के नहीं हैं। एल 2 में प्रेजेंटेशन ऑब्जेक्ट्स शामिल हैं जिन्हें प्रदर्शन और ग्रिड ब्लिंकिंग व्यवहार के बारे में अपडेट किया जाना चाहिए। –

उत्तर

5

शुरुआत के लिए मैं उत्परिवर्तनीय संरचना से छुटकारा पाउंगा। परिवर्तनीय मूल्य प्रकार एक मौलिक रूप से बुरी चीज हैं। (सार्वजनिक क्षेत्र हैं, आईएमओ।)

शायद यह एक शब्दकोश बनाने के लायक है ताकि आप आसानी से दो सूचियों की सामग्री की तुलना कर सकें। एक बार जब आपको उपस्थिति/अनुपस्थिति की जांच करने का यह आसान तरीका मिल जाए, तो बाकी को सीधा होना चाहिए।

हालांकि ईमानदार होने के लिए, ऐसा लगता है कि आप मूल रूप से एल 2 को एल 1 की पूरी प्रतिलिपि बनाना चाहते हैं ... स्पष्ट एल 2 और बस AddRange को कॉल करें? या यह मुद्दा है कि आप एल 2 बदलते समय भी अन्य कार्रवाइयां लेना चाहते हैं?

+0

मैं mutable structs, और सार्वजनिक क्षेत्रों के बारे में सहमत हूं। लेकिन खाता प्रकार वास्तव में यहां महत्वपूर्ण नहीं है - यह एक वर्ग हो सकता है, इसमें encapsulation और समानता सदस्य हैं, आदि। मैं एल 1 वस्तुओं द्वारा एल 2 वस्तुओं के उदाहरणों को प्रतिस्थापित नहीं करने की देखभाल करके दो सूचियों को सिंक्रनाइज़ करने पर केंद्रित हूं। एल 2 वस्तुओं को अद्यतन किया जाना है। –

0

जॉन स्कीट की टिप्पणी के अलावा, आपके खाते को एक वर्ग बनाते हैं और बराबर समानता जांच प्राप्त करने के लिए समान() और GetHashCode() विधि को ओवरराइड करते हैं।

0

एल 2 = एल 1.क्लोन()?

... लेकिन मुझे लगता है कि आप कुछ उल्लेख करना भूल गए हैं।

2

यदि आपकी दो सूचियों को क्रमबद्ध किया गया है, तो आप आसानी से उनके माध्यम से चल सकते हैं। यह एक ओ (एम + एन) ऑपरेशन है। निम्नलिखित कोड मदद कर सकता है:

class Program 
{ 
    static void Main() 
    { 
     List<string> left = new List<string> { "Alice", "Charles", "Derek" }; 
     List<string> right = new List<string> { "Bob", "Charles", "Ernie" }; 

     EnumerableExtensions.CompareSortedCollections(left, right, StringComparer.CurrentCultureIgnoreCase, 
      s => Console.WriteLine("Left: " + s), s => Console.WriteLine("Right: " + s), (x,y) => Console.WriteLine("Both: " + x + y)); 
    } 
} 

static class EnumerableExtensions 
{ 
    public static void CompareSortedCollections<T>(IEnumerable<T> source, IEnumerable<T> destination, IComparer<T> comparer, Action<T> onLeftOnly, Action<T> onRightOnly, Action<T, T> onBoth) 
    { 
     EnumerableIterator<T> sourceIterator = new EnumerableIterator<T>(source); 
     EnumerableIterator<T> destinationIterator = new EnumerableIterator<T>(destination); 

     while (sourceIterator.HasCurrent && destinationIterator.HasCurrent) 
     { 
      // While LHS < RHS, the items in LHS aren't in RHS 
      while (sourceIterator.HasCurrent && (comparer.Compare(sourceIterator.Current, destinationIterator.Current) < 0)) 
      { 
       onLeftOnly(sourceIterator.Current); 
       sourceIterator.MoveNext(); 
      } 

      // While RHS < LHS, the items in RHS aren't in LHS 
      while (sourceIterator.HasCurrent && destinationIterator.HasCurrent && (comparer.Compare(sourceIterator.Current, destinationIterator.Current) > 0)) 
      { 
       onRightOnly(destinationIterator.Current); 
       destinationIterator.MoveNext(); 
      } 

      // While LHS==RHS, the items are in both 
      while (sourceIterator.HasCurrent && destinationIterator.HasCurrent && (comparer.Compare(sourceIterator.Current, destinationIterator.Current) == 0)) 
      { 
       onBoth(sourceIterator.Current, destinationIterator.Current); 
       sourceIterator.MoveNext(); 
       destinationIterator.MoveNext(); 
      } 
     } 

     // Mop up. 
     while (sourceIterator.HasCurrent) 
     { 
      onLeftOnly(sourceIterator.Current); 
      sourceIterator.MoveNext(); 
     } 

     while (destinationIterator.HasCurrent) 
     { 
      onRightOnly(destinationIterator.Current); 
      destinationIterator.MoveNext(); 
     } 
    } 
} 

internal class EnumerableIterator<T> 
{ 
    private readonly IEnumerator<T> _enumerator; 

    public EnumerableIterator(IEnumerable<T> enumerable) 
    { 
     _enumerator = enumerable.GetEnumerator(); 
     MoveNext(); 
    } 

    public bool HasCurrent { get; private set; } 

    public T Current 
    { 
     get { return _enumerator.Current; } 
    } 

    public void MoveNext() 
    { 
     HasCurrent = _enumerator.MoveNext(); 
    } 
} 

आप हालांकि, उन पर पुनरावृत्ति जबकि संग्रह संशोधित करने के बारे में सावधान रहना होगा।

यदि वे क्रमबद्ध नहीं होते हैं, तो प्रत्येक तत्व को प्रत्येक तत्व में एक दूसरे के साथ तुलना करना ओ (एमएन) है, जो वास्तव में दर्दनाक हो जाता है।

यदि आप प्रत्येक संग्रह से मुख्य मूल्यों को एक शब्दकोश या इसी तरह की प्रतिलिपि बना सकते हैं (यानी।"एक्स एक्स मौजूद है" पूछे जाने पर स्वीकार्य प्रदर्शन के साथ एक संग्रह?), तो आप कुछ उचित के साथ आ सकते हैं।

+0

ठीक है, आपको ओ (एन * लॉग (एन) + एम * लॉग (एम) से बेहतर कुछ के साथ आने की जरूरत है, अन्यथा मैं सिर्फ सूचियों को सॉर्ट करूंगा और अपना पहला दृष्टिकोण उपयोग करूंगा :) – Tetha

0

मुझे पता है कि यह एक पुरानी पोस्ट है लेकिन आपको ऑटोमैपर की जांच करनी चाहिए। यह वही करेगा जो आप एक बहुत ही लचीला और विन्यास योग्य तरीके से करना चाहते हैं।

AutoMapper