Pregunta

Tengo una colección de cadenas en C #. Cada cadena es una oración que puede aparecer en una página. También tengo una colección de saltos de página que es una colección de int. representa el índice donde la colección de cadenas se divide en una nueva página.

Ejemplo: Cada 10 elementos en la colección de cadenas es una página, por lo que la colección de saltos de página sería una colección de int con los valores de 10, 20, 30. ...

Entonces, si hay 2 páginas de cadenas, habrá 1 elemento en la colección de saltos de página y si hay 1 página, la colección de salto de página tendrá cero elementos.

Estoy intentando crear la siguiente función:

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

He intentado varias veces escribir esta función y sigo encontrando declaraciones complejas if y switch para tener en cuenta los documentos de una o dos páginas y los números de página que se solicitan fuera del rango (por ejemplo, la última página debe devolverse si el número de página es mayor que el número de páginas y la primera página si el número de página es 0 o menos).

Mi lucha con este problema me lleva a formular la pregunta: ¿Existe un patrón o algoritmo bien conocido para abordar este tipo de consulta de subconjunto?

¿Fue útil?

Solución

" Puro " Linq no es una buena opción para este problema. Lo mejor es confiar en los métodos y propiedades de la Lista (T). No hay muchos casos especiales.

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

No quieres reemplazar la propiedad .Count con el método .Count () de linq. No desea reemplazar el método .GetRange () con los métodos .Skip (n) .Take (m) de linq.

Linq sería mejor si quisieras proyectar estas colecciones en otras colecciones:

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

Otros consejos

No estoy seguro de para qué sirve la lista de saltos de página. Lo pensaría de esta manera. Una colección de cadenas, un número de página y el tamaño de la página. Entonces podrías hacer 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();

En el caso de que el número de páginas varíe según la página según su comentario, intente algo como a continuación. Es posible que deba ajustar la comprobación de la condición del borde ...

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top