2016-06-01 1 views
3

모든 컬렉션에 Spring4D를 사용하고 있습니다.IsFirst 및 IsLast 함수가있는 열거자를 구현하는 방법은 무엇입니까?

이제는 열거 자의 현재 값이 첫 번째 (쉬운 것) 또는 마지막 (열심히) 컬렉션에 있는지 여부를 알아야 할 상황이 있습니다.

program Project1; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, 
    Spring.Collections; 

var 
    Enumerable: IEnumerable<Integer>; 
    Enumerator: IEnumerator<Integer>; 

begin 
    Enumerable := TEnumerable.Query<Integer>(TArray<Integer>.Create(1, 2, 3, 4, 5) 
    ) as IEnumerable<Integer>; 
    Enumerator := Enumerable.GetEnumerator; 
    while Enumerator.MoveNext do 
    begin 
    WriteLn('Value = ', Enumerator.Current); 
    WriteLn('First in collection? ', Enumerator.CurrentIsFirst); 
    WriteLn('Last in collection? ', Enumerator.CurrentIsLast); 
    end; 
    ReadLn; 

end. 

CurrentIsFirst

첫번째 값이 전달되면 리셋 로컬 부울을 사용하여 구현 될 수있다.

그러나 구현하기 쉬운 방법을 모르겠다. CurrentIsLast.

메모리에 너무 많은 값이 포함될 수 있으므로 지연 수집을 처리 할 수 ​​있어야합니다.

어떻게 CurrentIsLast 기능을 구현할 수 있습니까? - 당신은 그냥 현재 요소를 버퍼 및 볼 필요가

if Enumerator.MoveNext then 
begin 
    flag := True; 
    repeat 
    WriteLn('Value = ', Enumerator.Current); 
    WriteLn('First in collection? ', flag); 
    flag := not Enumerator.MoveNext; 
    WriteLn('Last in collection? ', flag); 
    until flag; 
end; 

이 기본 알고리즘하지만 IsFirst/IsLast을 제공하기 위해 IEnumerator<T>위한 장식에 그것을 넣을 수 있습니다 :

+0

저는 요소가 첫 번째인지 마지막인지 전혀 다른 방식으로 해결할 수없는 경우 지식을 통해 무엇을 얻으려고하는지 궁금합니다. –

+0

우리는 다소 특별한 형태의 [control break] (https://en.wikipedia.org/wiki/Control_break)에 사용하고 있습니다. –

+0

내가 말했듯이 이것을 할 수있는 또 다른 방법이있을 수 있습니다. 예를 들어 링크 된 위키피디아 기사에서 TEnumerable.GroupBy로 그룹화 할 수 있습니다. –

답변

6

그냥 반복하는 동안 플래그를 사용 하나는 앞으로 볼 수 있습니다.

type 
    IEnumeratorEx<T> = interface(IEnumerator<T>) 
    function IsFirst: Boolean; 
    function IsLast: Boolean; 
    end; 

    TEnumeratorState = (Initial, First, Only, Running, Last, Finished); 
    TEnumeratorEx<T> = class(TEnumeratorBase<T>, IEnumeratorEx<T>) 
    private 
    fSource: IEnumerator<T>; 
    fCurrent: T; 
    fState: TEnumeratorState; 
    function IsFirst: Boolean; 
    function IsLast: Boolean; 
    protected 
    function GetCurrent: T; override; 
    function MoveNext: Boolean; override; 
    public 
    constructor Create(const source: IEnumerator<T>); 
    end; 

constructor TEnumeratorEx<T>.Create(const source: IEnumerator<T>); 
begin 
    inherited Create; 
    fSource := source; 
end; 

function TEnumeratorEx<T>.GetCurrent: T; 
begin 
    Result := fCurrent; 
end; 

function TEnumeratorEx<T>.IsFirst: Boolean; 
begin 
    Result := fState in [First, Only]; 
end; 

function TEnumeratorEx<T>.IsLast: Boolean; 
begin 
    Result := fState in [Only, Last]; 
end; 

function TEnumeratorEx<T>.MoveNext: Boolean; 
begin 
    case fState of 
    Initial: 
     if fSource.MoveNext then 
     fState := First 
     else 
     fState := Finished; 
    First: 
     fState := Running; 
    Only, Last: 
     fState := Finished; 
    end; 

    Result := fState <> Finished; 
    if Result then 
    begin 
    fCurrent := fSource.Current; 
    if not fSource.MoveNext then 
     Inc(fState); 
    end; 
end; 
관련 문제