문제

C# 문자열 컬렉션이 있습니다. 각 문자열은 페이지에 표시 될 수있는 문장입니다. 또한 INT 모음 인 페이지 브레이크 모음이 있습니다. 문자열 모음이 새 페이지로 분할되는 인덱스를 나타냅니다.

예 : 문자열 컬렉션의 각 10 개 항목은 페이지이므로 페이지 브레이크 모음은 값이 10, 20, 30의 int 모음이 될 것입니다.

따라서 문자열의 2 페이지가 있으면 페이지 브레이크 컬렉션에 1 개의 항목이 있고 1 페이지가 있으면 페이지 브레이크 컬렉션에 항목이 0이됩니다.

다음과 같은 기능을 만들려고합니다.

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

이 기능을 작성하는 데 약간의 찌르기를했고 단일 및 2 페이지 문서와 페이지 번호가 범위 밖에서 요청되는 단일 및 2 페이지 문서와 페이지 번호를 고려하여 복잡한 if 및 스위치 명세서를 계속 생각해냅니다 (예 : 페이지 번호가있는 경우 마지막 페이지를 반환해야합니다. 페이지 수보다 큰 경우 페이지 번호가 0 이하인 경우 첫 페이지).

이 문제와의 투쟁은 다음과 같이 질문하게됩니다.이 유형의 서브 세트 쿼리를 해결하기 위해 잘 알려진 패턴이나 알고리즘이 있습니까?

도움이 되었습니까?

해결책

"순수한"LINQ는이 문제에 적합하지 않습니다. 가장 적합한 것은 목록 (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)
    }
  );

다른 팁

페이지 브레이크 목록이 무엇인지 확실하지 않습니다. 나는 이런 식으로 생각할 것이다. 문자열 모음, 페이지 번호 및 페이지 크기. 그런 다음 다음과 같은 작업을 수행 할 수 있습니다.

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 );
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top