Domanda

Ho una raccolta di stringhe C #. Ogni stringa è una frase che può apparire su una pagina. Ho anche una raccolta di interruzioni di pagina che è una raccolta di int. che rappresenta l'indice in cui la raccolta di stringhe viene suddivisa in una nuova pagina.

Esempio: ogni 10 elementi nella raccolta di stringhe è una pagina, quindi la raccolta di interruzioni di pagina sarebbe una raccolta di int con i valori di 10, 20, 30. ...

Quindi se ci sono 2 pagine di stringhe ci sarà 1 elemento nella raccolta di interruzioni di pagina e se c'è 1 pagina, la raccolta di interruzioni di pagina avrebbe zero elementi.

Sto cercando di creare la seguente funzione:

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

Ho preso alcune pugnalate nello scrivere questa funzione e continuo a elaborare complesse istruzioni if ??e switch per tenere conto dei documenti a una o due pagine e dei numeri di pagina richiesti al di fuori dell'intervallo (es. l'ultima pagina deve essere restituita se il numero di pagina è maggiore del numero di pagine e della prima pagina se il numero di pagina è 0 o inferiore).

La mia lotta con questo problema mi porta a porre la domanda: esiste un modello o un algoritmo ben noto per affrontare questo tipo di query del sottoinsieme?

È stato utile?

Soluzione

" Pure " Linq non è adatto a questo problema. La soluzione migliore è fare affidamento sui metodi e sulle proprietà dell'elenco (T). Non ci sono molti casi speciali.

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

Non si desidera sostituire la proprietà .Count con il metodo .Count () di linq. Non si desidera sostituire il metodo .GetRange () con i metodi .Skip (n) .Take (m) di linq.

Linq sarebbe più adatto se volessi proiettare queste raccolte in altre raccolte:

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

Altri suggerimenti

Non so a cosa serva l'elenco delle interruzioni di pagina. Ci penserei così. Una raccolta di stringhe, un numero di pagina e le dimensioni della pagina. Quindi potresti fare qualcosa del tipo:

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

Nel caso in cui il numero di pagine vari per pagina secondo il tuo commento, prova qualcosa di simile di seguito. Potrebbe essere necessario regolare le condizioni del bordo controllando ...

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 );
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top