выбор и пропуск элементов - PullRequest
1 голос
/ 19 июля 2010

Я пытаюсь улучшить какой-то код, и я не могу придумать лучшего способа сделать то, что он делает в настоящее время.по сути, я зацикливаюсь снаружи на количество элементов, деленное на число, которое я хочу выбрать, затем внутри этого цикла я выбираю элемент на основе внутреннего цикла из числа элементов, которые мне нужны, чтобы создать один элемент, модифицируя его значением по внешнему циклу,поэтому в приведенном ниже примере внешний цикл выполняется дважды (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);
    }

Таким образом, мы заканчиваем список List с 2 элементами, каждый элемент содержит 2 XElements каждый (один иДва вместе и три и четыре вместе) так ..

ItemOne
 One
 Two
ItemTwo
 Three
 Four

Ответы [ 2 ]

2 голосов
/ 19 июля 2010

Есть простой способ сделать это с помощью одного оператора 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>> в структуре, которую вы описываете.

2 голосов
/ 19 июля 2010
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();
...