Pergunta

Eu tenho um C # coleção de strings. Cada corda é uma frase que pode aparecer em uma página. Eu também tenho uma coleção de quebras de página que é uma coleção de int de. representando o índice onde a coleção de cordas são de divisão para uma nova página.

Exemplo: Cada 10 itens na coleção string é uma página para a coleta de quebras de página seria uma coleção de int do com os valores de 10, 20, 30. ...

Assim, se houver 2 páginas de cordas, em seguida, haverá um item na coleção de quebra de página e, se houver uma página, então a coleção de quebra de página iria ter zero itens.

Eu estou tentando criar a seguinte função:

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

Eu tenho tido algumas facadas em escrever esta função e continuar chegando com complexo if e switch de levar em conta única e dois documentos de página e números de página que está sendo solicitado fora do intervalo (por exemplo, a última página deve ser devolvido se número da página é maior do que o número de páginas e primeira página se o número de página é 0 ou menos).

A minha luta com este problema leva-me a fazer a pergunta: Existe um padrão bem conhecido ou algoritmo para resolver este tipo de subconjunto consulta ?

Foi útil?

Solução

"Pure" Linq não é um bom ajuste para este problema. O melhor ajuste é contar com os métodos e propriedades de List (T). Não há -that- muitos casos especiais.

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

Você não quer substituir a propriedade .Count com o método de linq .Count (). Você não quer para substituir o método com .Skip (n) .Pegue (m) métodos LINQ .GetRange ().

Linq seria um ajuste melhor se você queria projetar essas coleções em outras coleções:

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

Outras dicas

Não é certo que a lista de quebras de página é para. Gostaria de pensar nisso desta maneira. Uma coleção de cordas, um número de página, eo tamanho da página. Então você poderia fazer algo como:

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

No caso em que o número de páginas pode variar por página de acordo com o seu comentário, tente algo como abaixo. Pode ser necessário ajustar a verificação de condição de borda ...

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 );
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top