Frage

Ich habe eine C # Sammlung von Strings. Jede Saite ist ein Satz, der auf einer Seite angezeigt werden kann. Ich habe auch eine Sammlung von Seitenumbrüchen, die eine Sammlung von int das ist. die den Index, in dem die Sammlung von Strings auf eine neue Seite aufgespalten wird.

Beispiel: Je 10 Elemente in der String-Kollektion ist eine Seite, so dass die Sammlung von Seitenumbrüchen von 10 eine Sammlung von int die mit den Werten sein würde, 20, 30 ...

Wenn es also zwei Seiten von Strings, dann wird es ein Element in der Seitenumbruch Sammlung sein und wenn es 1 Seite dann der Seitenumbruch Sammlung würde Null Elemente hat.

Ich versuche, die folgende Funktion zu erstellen:

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

Ich habe ein paar Stichen auf das Schreiben dieser Funktion genommen und halten auf mit komplexen kommen, wenn und switch-Anweisungen zu berücksichtigen, ein- und zweiseitige Dokumente und Seitenzahlen außerhalb des Bereichs angefordert werden (zB letzte Seite zurückgegeben werden soll, wenn Seitennummer größer ist als die Anzahl der Seiten und die erste Seite, wenn Seitennummer 0 oder weniger ist).

Mein Kampf mit diesem Problem führt mich die Frage: Gibt es ein gut bekanntes Muster oder Algorithmus diese Art von Teilmenge Abfrage Adresse

?
War es hilfreich?

Lösung

„Pure“ Linq ist nicht eine gute Passform für dieses Problem. Die beste Lösung ist auf die Methoden und Eigenschaften der List (T) zu verlassen. Es gibt nicht viele Sonderfälle -that-.

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

Sie wollen nicht die .Count Eigenschaft mit Linq der .Count () -Methode ersetzen. Sie wollen nicht den .GetRange () -Methode mit Linq des .skip (n) .Nehmen (m) Methoden ersetzen.

Linq wäre eine bessere Passform, wenn Sie diese Sammlungen in anderen Sammlungen projizieren wollte:

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

Andere Tipps

Nicht sicher, was die Liste der Seitenumbrüche für. Ich würde auf diese Weise daran denken. Eine Sammlung von Strings, eine Seitenzahl und die Größe der Seite. Dann könnten Sie so etwas wie:

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

In dem Fall, dass die Anzahl der Seiten pro Seite variiert nach Ihrem Kommentar, versuchen Sie so etwas wie unten. Möglicherweise müssen Sie die Randbedingung Prüfung einstellen ...

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 );
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top