选择和跳过元素

时间:2010-07-19 18:47:19

标签: c# linq .net-3.5 linq-to-xml

我正在尝试改进一些代码,我想不出更好的方法来做它目前的工作。基本上我循环外面的项目数除以我想要选择的数字,然后在该循​​环内我根据我需要创建一个项目的内部循环选择项目,通过外循环值修改该项目,所以在下面的例子中,外部循环循环两次(0,1),内部循环每个外部循环两次(0,1然后是2,3)。

任何人都可以看到一种更易读的方法来执行此操作或者在不执行这两个循环的情况下执行此操作吗?

希望这是有道理的。感谢。

考虑

的XML
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);

这里的Select值告诉我有多少项创建一个“对象”所以在这种情况下,2个项目是一个对象(这可以是任何数字,但项目数量总是允许正确数量的对象)目前我是做某事像

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

所以我们以一个包含2个项目的List列表结束,每个项目分别包含2个XElements(一个和两个一起,三个和四个一起) 所以..

ItemOne
 One
 Two
ItemTwo
 Three
 Four

2 个答案:

答案 0 :(得分: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; 
  } 
} 

被叫

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

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

答案 1 :(得分:2)

使用单个LINQ语句有一种简单的方法。您可以按item index / batchSize分组,如下所示:

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

这会在您描述的结构中给出IEnumerable<IEnumerable<XElement>>