2012-08-16 2 views
1

정렬되어 있으며 고유 한 파일 이름이 포함 된 TStringList가 있습니다. 목록의 크기는 다양 할 수 있습니다 (따라서 수십만 개의 항목이 될 수 있습니다). 항목 중 특정 문자열 (예 : 파일이 하위 폴더에있는 경우)로 시작하는지 확인하고 싶습니다. 순차적으로 목록을 스캔하고 StartsText를 사용하기는 쉽지만 이상적인 솔루션은 아닙니다.정렬 된 TStringList에서 접두사가있는 항목 검색 (StartsText)

TStringList.Find() 코드를 시작점으로 사용하여 솔루션이라고 생각하는 함수를 만들었지 만 확실하게 알고 싶습니다. 기본적으로

function ShortcutFind(const S: string): Boolean; 
    var 
    L, H, I, C: Integer; 
    begin 
    Result := False; 
    L := 0; 
    H := FList.Count - 1; 
    while L <= H do begin 
     I := (L + H) shr 1; 

     if TFilenameUtils.StartsFilename(FList[I], aFolder) then begin 
     Result:=TRUE; 
     Exit; 
     end; 

     C := FList.CompareStrings(FList[I], S); 
     if C < 0 then 
     L := I + 1 
     else begin 
     H := I - 1; 
     if C = 0 then begin 
      Result := True; 
      if FList.Duplicates <> dupAccept then L := I; 
     end; 
     end; 
    end; 
    end; 

, 유일한 진짜 변화가 없다는 것입니다 : 클래스 (FList가 검색되는 TStringList를 인스턴스이다), 그리고 StartsFilename가 StartsText와 같은 방식으로 작동의 구성원이되지 다음에 대해 걱정하지 마십시오 비교하기 위해 다음 항목으로 이동하기 전에 확인하십시오.

TStringList에서 전환하는 것은 옵션이 아닙니다.

이 방법이 효과가 있습니까?

감사

TFilenameUtils.StartsFilenameStartsText, 당신이 그것을 복사하는 대신 TStringList.Find를 사용 하여 하나 개의 문장에서 전체 기능을 수행 할 수 있습니다 (귀하의 첫 번째 단락이 될 수있는 제안)와 같은 경우
+3

"작동하니?" 그냥 시도하고 알아낼 수 없니? 이 코드는 더 간단 할 수 있지만 코드에 대한 비판을 원한다면 Stack Overflow의 "코드 검토"사이트로 이동할 수 있습니다. 그렇지 않으면, 당신이 정말로 요구하는 것이 확실하지 않습니다. –

+0

테스트를 위해 테스트 루틴을 작성했으며 제대로 작동하는 것 같습니다. 나는 TStringList를 유지하는 제약 하에서 명백한 구멍이나 더 나은/더 빠른 방법이 필요한지 정말로 묻고있는 것 같습니다. Tnaks. – Mick

+0

효율성이 중요합니까? 이진 검색으로 전환하면 해당 지역에서 빠르게 승리 할 수 ​​있습니다. – boileau

답변

9

:

var 
    I: Integer; 
begin 
    Assert(not FList.CaseSensitive); 
    Result := FList.Find(S, I) or ((I < FList.Count) and StartsText(S, FList[I])); 
end; 

Find에 오류가 발생하더라도 여전히 원하는 문자열 의 색인이 인 목록이 나타납니다. 접두어 문자열을 검색 할 때 그 접두사는 해당 접두어로 시작하는 다른 문자열 앞에 위치하므로 접두어가있는 문자열이 있으면 가상 접두사 자체의 위치 바로 뒤에 나타납니다. 당신이 당신의 현재 코드를 유지하려면


, 당신은 C = 0를 확인하는 조건을 제거하여 단순화 할 수 있습니다. 귀하의 StartsFilename 기능이 고장 나지 않는 한, 그 상태는 결코 일어나서는 안됩니다. 그러나 함수가 실제로 깨져서 C일 수있는 경우이 0이면 원하는 것을 찾은 후 그 시점에서 루프 실행을 중지 할 수 있습니다. 어느 방법을 사용하든 함수에 Find과 동일한 요구 사항이 없으므로 찾은 항목의 색인을 반환하지 않으므로 Duplicates을 확인할 필요가 없습니다.

+0

.Size는 실제로 .Count 여야한다고 가정합니다. – Mick

+0

+1. @Mick : 예. 나는 Rob에게 그것을 고쳤다. –