2010-07-19 7 views
1

J'essaye d'améliorer du code et je ne peux pas penser à une meilleure manière de faire ce qu'elle fait actuellement. essentiellement i boucle dehors pour le nombre d'éléments divisés par le nombre que je veux sélectionner, puis dans cette boucle je sélectionne l'élément basé sur une boucle interne du nombre d'éléments dont j'ai besoin pour créer un seul élément modifiant cela par la valeur outerloop, Ainsi, dans l'exemple ci-dessous, la boucle externe boucle deux fois (0,1) et la boucle interne deux fois par boucle externe (0,1 puis 2,3).sélectionner et ignorer des éléments

Quelqu'un peut-il voir une façon plus lisible de le faire ou un moyen de le faire sans faire les deux boucles?

Espérons que cela a du sens. Merci.

Tenir compte XML de

string xml = @" 
<MainItem> 
<Select>2</Select> 
<ItemArray> 
    <Item>One</Item> 
    <Item>Two</Item> 
    <Item>Three</Item> 
    <Item>Four</Item> 
</ItemArray> 
</MainItem>"; 

var doc = XDocument.Parse(xml); 

Voici la valeur Select me dit combien d'éléments créent un « objet » dans ce cas 2 articles sont un objet (cela peut être un nombre, mais le nombre d'articles seront toujours autorise le nombre correct d'objets) actuellement je suis en train de faire somethng comme

List<List<XElement>> items = new List<List<XElement>>(); 
    for(int i = 0;i < (doc.Descendants("Item").Count()/(int)doc.Element("MainItem").Element("Select"));i++) 
    { 
     //this is one object 
    var singleItem = new List<XElement>(); 
     for (int j = 0; j < (int)doc.Element("MainItem").Element("Select"); j++) 
    { 
     var item = doc.Descendants("Item").ElementAt(j + (i * (int)doc.Element("MainItem").Element("Select"))); 
     singleItem.Add(item); 
    } 
    items.Add(singleItem); 
    } 

nous terminons avec une liste de liste avec 2 éléments, chaque élément peut contenir 2 XElements chacun (un et deux et trois et quatre ensemble) donc ..

ItemOne 
One 
Two 
ItemTwo 
Three 
Four 
+1

Vous devriez probablement formater votre XML et montrer un échantillon de la sortie XML que vous attendez. –

+0

@Winston Smith fait comme demandé, merci pour l'entrée – Pharabus

+0

Combien de fois allez-vous recalculer cet '' (int) doc.Element ("MainItem"). Element ("Select") '? –

Répondre

2

Il y a une façon simple de le faire avec une seule instruction LINQ. Vous pouvez regrouper par item index/batchSize, comme suit:

int batchSize = (int)doc.Element("MainItem").Element("Select"); 
var items = doc 
      .Descendants("Item") 
      .Select((e, i) => new {i,e}) 
      .GroupBy(g => g.i/batchSize) 
      .Select(g => g.Select(gv => gv.e)) 
      ; 

Cela donne une IEnumerable<IEnumerable<XElement>>, dans la structure que vous décrivez.

+0

parfait, merci – Pharabus

2
public static IEnumerable<List<T>> Batch<T>(
    this IEnumerable<T> source, 
    int batchAmount) 
{ 
    List<T> result = new List<T>(); 
    foreach(T t in source) 
    { 
    result.Add(t); 
    if (result.Count == batchSize) 
    { 
     yield return result; 
     result = new List<T>(); 
    } 
    } 
    if (result.Any()) 
    { 
    yield return result; 
    } 
} 

Appelée par

int batchAmount = (int)doc.Element("MainItem").Element("Select")); 

List<List<XElement>> items = doc.Descendants("Item") 
    .Batch(batchAmount) 
    .ToList(); 
+0

souhaite que je puisse accepter 2 réponses +1 cela fonctionne et réalise ce dont j'avais besoin, seule différence entre le vôtre et la réponse acceptée est le besoin d'une méthode d'extension – Pharabus

+0

Winston Smith's réponse est cool (je l'ai écrit avant), mais lent lorsqu'il est utilisé plus de 10 000 éléments. –

Questions connexes