0

I have a list of strings list and a number pageSize, a pageNumber and a rowNumber. I want to split this list by the page size and create a list of list, then return the element at the given pageNumber and rowNumber. If the page number and row number is above the possible index level, return null. Both pageNumber and rowNumber are zero-based indexes.

Example:

list = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
pageSize = 3
pageNumber = 2
rowNumber = 1
Result:List = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
Result = 8.

But this code is throwing an OutOfRange exception:

public static int? GetItemInThePagedDataList(IEnumerable<int> list, int pageSize, int pageNumber, int rowNumber)
{
    var lists = list.Chop(pageSize);
    if (pageNumber >= lists.Count() || rowNumber >= lists.First().Count())
    {
        throw new ArgumentOutOfRangeException();
    }
    return lists.ElementAt(pageNumber).ElementAt(rowNumber);
}
Jon Adams
  • 24,464
  • 18
  • 82
  • 120
  • There's no need to split the original list. You can just use the formula index = pageSize * pageNumber + rowNumber . – juharr Jul 17 '17 at 12:45
  • 1
    Possible duplicate of [Create batches in linq](https://stackoverflow.com/questions/13731796/create-batches-in-linq) – mjwills Jul 17 '17 at 12:48

3 Answers3

1

Don't need to split list. Write a function like this and return element at index.

public static int? GetItemInThePagedDataList(IEnumerable list, int pageSize, int pageNumber, int rowNumber) 
{
    int index = (pageSize * pageNumber) + rowNumber; 
    return list.ElementAt(index);
}
Kemal Güler
  • 608
  • 1
  • 6
  • 21
  • @ kemal guler, I have tried your code kemal, i get the same exception (outofreach) – Roy Guzman Jul 17 '17 at 13:23
  • Don't send your list type as IEnumerable. Send type as var or string. @RoyGuzman – Kemal Güler Jul 17 '17 at 13:47
  • @mjwills: What are you advocating then? `.Skip(index-1).First()`? – Flater Jul 17 '17 at 15:29
  • I removed my comment @Flater - it didn't make sense. – mjwills Jul 18 '17 at 00:28
  • public static int? GetItemInThePagedDataList(IEnumerable list, int pageSize, int pageNumber, int rowNumber) { int index = (pageSize * pageNumber) + rowNumber; return list.ElementAtOrDefault(index); }.....this is another variant that worked too. – Roy Guzman Jul 18 '17 at 09:19
  • yes very true. :) Thanks again mjwills.............please see my other question, I am struggling with it http://www.c-sharpcorner.com/forums/how-to-find-all-files-to-another-destination I am blocked for another day to post more questions here cause last time I posted a question I did not know I have to post my attempt with it. I had bad reviews. sad really. i did not know it was my first day. – Roy Guzman Jul 18 '17 at 14:36
  • You would be best to post that question here at stackoverflow rather than at c-sharpcorner @RoyGuzman . – mjwills Jul 18 '17 at 23:08
  • I am truly struggling with c#, If i get through the first 2 weeks I will be put through intense training but I am have to get through the first 2 weeks. please mjwills free few minutes of your time on friday 21/7/2017, I will appreciate it and i will carry it forward once I am more skilled. @ kemal guler – Roy Guzman Jul 19 '17 at 13:41
1

This is a variant of Kemal's solution. This implementation will return null if the page number and row number are above the possible index level. I have also implemented it twice (once for IEnumerable, once for IList) so that performance is dramatically improved for List scenarios.

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    public static int? GetItemInThePagedDataList(IEnumerable<int> list, int pageSize, int pageNumber, int rowNumber)
    {
        var index = (pageSize * pageNumber) + rowNumber;
        var nullableList = list.Select(z => (int?) z);
        return index < 0 ? null : nullableList.ElementAtOrDefault(index);
    }

    public static int? GetItemInThePagedDataList(IList<int> list, int pageSize, int pageNumber, int rowNumber)
    {
        var index = (pageSize * pageNumber) + rowNumber;
        return (index >= list.Count || index < 0) ? (int?)null : list[index];
    }

    static void Main(string[] args)
    {
        var list = new List<int> {1, 2, 3, 4};
        IEnumerable<int> items = list;  

        Console.WriteLine(GetItemInThePagedDataList(list, 2, 1, 1));
        Console.WriteLine(GetItemInThePagedDataList(items, 2, 1, 1));
        Console.WriteLine(GetItemInThePagedDataList(list, 2, 4, 1));
        Console.WriteLine(GetItemInThePagedDataList(items, 2, 4, 1));
        Console.WriteLine(GetItemInThePagedDataList(list, 2, -1, 1));
        Console.WriteLine(GetItemInThePagedDataList(items, 2, -1, 1));
    }
}
mjwills
  • 23,389
  • 6
  • 40
  • 63
  • Thank you so much guys, it was the last exercise in our list. I have 2 other trainees with me here and they are sending their regards too. we really couldn't figure it out, Thank you again. :) (a) mjwills and @kemal – Roy Guzman Jul 18 '17 at 09:18
  • Thank you again, now I know how to accept a solution :) – Roy Guzman Jul 20 '17 at 14:29
0

As mentioned you don't need to create the pages first. But I found this question because I had a similar question where I did have a need to chunk my list into smaller pieces. I'm going to go ahead and answer your exact question with my example so anyone else that finds this question and does need to literally chunk their list up will have a workable solution.

var pageSize = 250
var pages = list
    .Select((x, i) => new {Item = x, Index = i})
    .GroupBy(x => x.Index / pageSize)
    .Select(x => x.Select(y => y.Item));

The above example will split your list into a list of pages each with size 250.

So to answer the question given a list of lists already, you can take the above and do something like return pages.ToList()[pageNumber].Skip(rowNumber).FirstOrDefault();

claudekennilol
  • 992
  • 2
  • 13
  • 26