2009-12-17 3 views
0

J'ai deux documents avec un schéma simple que je dois comparer:XDocument comparrison

doc actuelle:

<Sections> 
    <Section Number="1"/> 
    <Section Number="2"/> 
    <Section Number="4"/> 
    <Section Number="5"/> 
</Sections> 

précédent doc:

<Sections> 
    <Section Number="1"/> 
    <Section Number="2"/> 
</Sections> 

Le résultat de la comparaison sera une liste de sections qui ont été ajoutées au document en cours ... c'est-à-dire les sections du document en cours qui ne figurent pas dans le document précédent. Dans cet exemple, les sections 4 et 5 sont nouvelles.

Le document actuel et le document précédent peuvent contenir jusqu'à 20 000 enregistrements. L'approche suivante produit les résultats dont j'ai besoin mais semble être la mauvaise approche car elle passe plusieurs fois sur les ensembles de données et prend un certain temps à s'exécuter.

obtenir une liste des sections:

List<XElement> currenList = currentDoc.Descendants("Section").ToList(); 

obtenir les attributs dans la liste précédente

List<string> previousString = //get the attribute values... 
//get the new sections... 
var newSections = (from nodes in currentList 
        let att = nodes.Attribute("Number").Value 
        where !previousList.Contains(att) 
        select nodes) 

Quelle est la meilleure approche qui impliquerait moins de passes/conversions des jeux de données?

Répondre

0

Vous devriez regarder Except:

IEnumerable<int> currentList = currentDoc.Descendants("Section") 
         .Select(e => (int)e.Attribute("Number")); 
IEnumerable<int> previousList = previousDoc.Descendants("Section") 
         .Select(e => (int)e.Attribute("Number")); 

IEnumerable<int> newSections = currentList.Except(previousList); 
+0

Si vous avez besoin de la partie '' choisir l'attribut '' dans le code de Sections dans une partie plus importante de votre code, vous devriez penser à en faire une méthode d'extension. –

+0

Comment Except est-il implémenté? Si elle vérifie l'existence en passant à travers la liste entière avec chaque élément, c'est toujours le cas et l'algorithme N^2. – santosc

+0

Est-ce que cela compte vraiment? Tant que vous n'avez pas de problème de performance, ne vous souciez pas de l'améliorer. –

0

Vous pouvez utiliser un ensemble triée pour garder la trace.

SortedSet<string> sections = new Sort... 
List<XElement> diff = new Li... 

foreach (var node in previousList) 
    sections.Add(node.Attribute("Section").Value()); 

foreach (var node in currentList) 
    if (!sections.Contains(node.Attribute("Section").Value()); 
     diff.Add(node); 

ce utilise un peu de mémoire supplémentaire avec SortedSet, mais il devrait fonctionner n * log (n) depuis le contains() sur un ensemble Sorted se déroulera log (n). À la fin, diff devrait contenir la liste que vous cherchez.