Getting odd/even part of a sequence with LINQ

前端 未结 7 1300
再見小時候
再見小時候 2020-12-01 06:47

Say I have a list of all Projects, and that I group them by Category like this:

var projectsByCat = from p in Projects
                     


        
相关标签:
7条回答
  • 2020-12-01 06:58
    var text = "this is a test <string> to extract odd <index> values after split";
    var parts = text.Split(new char[] { '<', '>' });
    IEnumerable words = parts.Where(x => parts.ToList().IndexOf(x) % 2 == 1)
    

    words would contain "string" and "index"

    0 讨论(0)
  • 2020-12-01 07:00

    You can separate odd and even in your view using linq.

    //even 
    @foreach (var item in Model.Where((item, index) => index % 2 == 0))
    {
         //do the code
    }
    
    //odd
    @foreach (var item in Model.Where((item, index) => index % 2 != 0))
    {
         //do the code
    }
    
    0 讨论(0)
  • 2020-12-01 07:03

    The oddCategories and the evenCategories are backward.

    Indexes start a 0 not 1

    0 % 2 = 0

    0 index is odd.

    var oddCategories  = projectsByCat.Where((cat, index) => index % 2 == 0);
    
    var evenCategories = projectsByCat.Where((cat, index) => index % 2 != 0);
    
    0 讨论(0)
  • 2020-12-01 07:11

    If you're using LINQ to SQL or LINQ to Entities you should first fully materialize the results into memory:

    var oddCategories  = projectsByCat.ToList().Where((c,i) => i % 2 != 0);
    var evenCategories = projectsByCat.ToList().Where((c,i) => i % 2 == 0);
    

    It isn't possible to iterate through results on the database with an indexer without the use of a cursor, which either ORM framework does not do.

    0 讨论(0)
  • 2020-12-01 07:13

    The proper way to do this using LINQ, and avoiding multiple enumerations over the input, is to do a grouping or similar on whether each item is even or odd.

    A simple way using the overload for Select that mixes in an index coupled with ToLookup gives you what you want:

    var oddsAndEvens = input
        .ToList() // if necessary to get from IQueryable to IEnumerable
        .Select((item, index) => new { isEven = index % 2 != 0, item })
        .ToLookup(
            i => i.isEven,
            i => i.item);
    

    This will produce a Lookup<TKey, TElement> data structure that has the following benefit:

    If the key is not found in the collection, an empty sequence is returned.

    This means that after the above LINQ query you can do:

    var evens = oddsAndEvens[true];
    var odds = oddsAndEvens[false];
    
    0 讨论(0)
  • 2020-12-01 07:15

    Note that calling .ToList() twice for the same query is going query the database twice.

    It would be much better to cache the result in an intermediate list, then apply your predicate filtering:

    var projectsByCat =
        (from p in Projects
        group p by p.Category into g
        orderby g.Count() descending
        select new { Category = g.Key, Projects = g }).ToList();
    
    var oddCategories = projectsByCat.Where((cat, index) => index % 2 != 0);
    var evenCategories = projectsByCat.Where((cat, index) => index % 2 == 0);
    
    0 讨论(0)
提交回复
热议问题