Buffer 연산자
original page can be found here
Buffer 활용
Buffer 연산자를 사용하면 이전 프레임에서의 값과 현재 프레임에서의 값의 비교와 같이 스트림에 흐르는 메시지를 비교하는 것과 같은 작업을 손쉽게 처리할 수 있습니다.
이전 값과 현재 값의 비교가 필요하는 경우는 아래와 같은 예들이 있겠네요.
- 이전 프레임에서의 플레이어의 좌표와 지금 프레임에서의 플레이어의 좌표의 비교
- 이전 프레임에서의 마우스 좌표와 현재 프레임에서의 마우스 좌표의 비교.
Buffer 연산자를 사용할 때에는 몇 개를 모아서 스트림으로 방류할 것인지를 정하는 count 개수와 다음 방류시 이전 값중 몇 개를 버릴 것인지를 정하는 skip 개수를 지정할 수 있습니다.
Buffer ( count, skip )
Buffer 연산자 호출시 skip값을 지정하면 Buffer가 이벤트를 방류한 뒤 어느 타이밍에 다시 방류할지를 지정할 수 있습니다. skip값을 지정하지 않은 경우에는 Buffer가 지정한 count값과 같은 값을 skip값으로 설정합니다..
// Skip을 지정하지 않은 경우
Observable.Range ( 1 , 10 )
.Select ( x => x.ToString ())
.Buffer ( 2 ) // 2 개씩 정리 (방류 한 후에 2 개 날려에서 다음을 방류하는 .Buffer (2, 2)와 동일)
.Subscribe ( x =>
{
// Buffer의 내용을 표시
Debug.Log ( x.Aggregate <string> (( p, c ) => p.ToString () + "," + c.ToString ()));
});
위의 결과는 아래와 같습니다.
1,2
3,4
5,6
7,8
9,10
Observable.Range ( 1 , 10 )
.Select ( x => x . ToString ())
.Buffer ( 2 , 1 ) // 2 개씩 넣어. 방류 후 1 개 날려 방류
.Subscribe ( x =>
{
// Buffer의 내용을 표시
Debug.Log (x.Aggregate <string> (( p, c ) => p.ToString() + "," + c . ToString ()));
});
1,2
2,3
3,4
4,5
5,6
6,7
7,8
9,10
10
Observable.Range ( 1 , 10 )
.Select ( x => x . ToString ())
.Buffer ( 3 , 2 ) // 3 개씩 넣어. 방류 후 2 개 날려 방류
.Subscribe ( x =>
{
// Buffer의 내용을 표시
Debug.Log ( x.Aggregate < string > (( p , c ) => p.ToString () + "," + c.ToString ()));
});
1,2,3
3,4,5
5,6,7
7,8,9
9,10
Buffer의 Skip을 이용하면 쉽게 스트림의 값을 비교하는 것이 가능하다.
Buffer를 이용하여 이전 메시지와 현재 메시지의 차이 비교하기
this . UpdateAsObservable ()
.Select ( _ => this.transform.position )
.Buffer ( 2, 1 )
.Where ( x => x.Count == 2 ) // OnCompleted시 1 개만 흘러 나오는 것을 컷
.Select ( x => x.Last () - x.First ())
.Subscribe ( x => Debug.Log ( "Delta :" + x ));
다음은 Buffer(n, 1)을 이용해서 Update의 10회 호출시 Time.deltatime의 평균을 계산하는 코드이다.
this . UpdateAsObservable ()
.Select ( _ => Time.deltaTime )
.Buffer ( 10, 1 )
.Select ( x => x.Average ())
.Subscribe ( x => Debug . Log ( "Average :" + x ));
Pairsiwe 연산자
Pairwise 연산자는 Buffer(2, 1) 과 유사하게 사용할 수 있는 연산자입니다.
// Pairwise ()
Observable . Range ( 1 , 10 )
. Pairwise ()
. Subscribe ( x =>
Debug . Log ( string . Format ( "{0}, {1}" , x . Previous , x . Current ))
);
// Buffer (2,1)
Observable . Range ( 1 , 10 )
. Select ( x => x . ToString ())
. Buffer ( 2 , 1 )
. Subscribe ( x =>
{
// Buffer의 내용을 표시
Debug . Log ( x . Aggregate < string > (( p , c ) => p . ToString () + "," + c . ToString ()));
});
아래는 결과입니다.
(Pairwise)
1,2
2,3
3,4
4,5
5,6
6,7
7,8
9,10
(Buffer)
1,2
2,3
3,4
4,5
5,6
6,7
7,8
9,10
10 // ←
Pairwise는 항상 쌍으로 값을 보내는 반면에 Buffer(2, 1)의 마지막 값은 skip으로 인해 하나만 들어온다 것이 다른 점입니다.