Алгоритм / шаблон для выбора подколлекций с использованием LINQ и C # - PullRequest
1 голос
/ 26 октября 2008

У меня есть коллекция строк в C #. Каждая строка - это предложение, которое может появиться на странице. У меня также есть коллекция разрывов страниц, которая является коллекцией целых. представляет индекс, в котором коллекция строк разделена на новую страницу.

Пример: каждые 10 элементов в коллекции строк являются страницами, поэтому коллекция разрывов страниц будет коллекцией целых чисел со значениями 10, 20, 30. ...

Таким образом, если есть 2 страницы строк, то в коллекции разрывов страниц будет 1 элемент, а если будет 1 страница, в коллекции разрывов страниц будет ноль элементов.

Я пытаюсь создать следующую функцию:

List<string> GetPage(List<string> docList, List<int> pageBreakList, int pageNum)
{
    // This function returns a subset of docList - just the page requested
}

Я сделал несколько попыток при написании этой функции и продолжаю придумывать сложные операторы if и switch для учета одностраничных и двухстраничных документов и номеров страниц, запрашиваемых вне диапазона (например, последняя страница должна возвращаться, если номер страницы больше, чем количество страниц и первой страницы, если номер страницы равен 0 или меньше).

Моя борьба с этой проблемой заставляет меня задать вопрос: существует ли хорошо известный шаблон или алгоритм для решения этого типа запроса подмножества?

Ответы [ 2 ]

4 голосов
/ 26 октября 2008

Не уверен, для чего предназначен список разрывов страниц. Я бы подумал об этом так. Коллекция строк, номер страницы и размер страницы. Тогда вы могли бы сделать что-то вроде:

List<string> strings = ...
int pageNum = ...
int pageSze = ...

if (pageNum < 1) pageNum = 1;
if (pageSize < 1) pageSize = 1;

List<string> pageOfStrings = strings.Skip( pageSize*(pageNum-1) ).Take( pageSize ).ToList();

В случае, если количество страниц зависит от вашего комментария, попробуйте что-то вроде ниже. Возможно, вам придется настроить проверку состояния кромки ...

List<string> strings = ...
List<int> sizes = ...

int pageNum = ...
int itemsToSkip =  0;
int itemsToTake = 1;

if (pageNum > 1)
{
   sizes.Take( pageNum - 2).Sum();

   if (pageNum <= sizes.Count)
   {
       itemsToTake = sizes[pageNum-1]
   }
{

List<string> pageOfStrings = strings.Skip( itemsToSkip ).Take( itemsToTake );
2 голосов
/ 26 октября 2008

«Чистый» Линк не подходит для этой проблемы. Лучше всего полагаться на методы и свойства List (T). Не так много особых случаев.

//pageNum is zero-based.
List<string> GetPage(List<string> docList, List<int> pageBreaks, int pageNum)
{

  // 0 page case
  if (pageBreaks.Count != 0)
  {
    return docList;
  }

  int lastPage = pageBreaks.Count;

  //requestedPage is after the lastPage case
  if (requestedPage > lastPage)
  {
    requestedPage = lastPage;
  }


  int firstLine = requestedPage == 0 ? 0  :
      pageBreaks[requestedPage-1];
  int lastLine = requestedPage == lastPage ? docList.Count :
      pageBreaks[requestedPage];

  //lastLine is excluded.  6 - 3 = 3 - 3, 4, 5

  int howManyLines = lastLine - firstLine;

  return docList.GetRange(firstLine, howManyLines);
}

Вы не хотите заменять свойство .Count методом linq .Count (). Вы не хотите заменять метод .GetRange () методами linq .Skip (n) .Take (m).

Лучше всего подойдет Linq, если вы хотите проецировать эти коллекции в другие коллекции:

IEnumerable<Page> pages =
  Enumerable.Repeat(0, 1)
  .Concat(pageBreaks)
  .Select
  (
    (p, i) => new Page()
    {
      PageNumber = i,
      Lines = 
        docList.GetRange(p, ((i != pageBreaks.Count) ? pageBreaks[i] : docList.Count)  - p)
    }
  );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...