From e4e8f5a361ba5a6c9802e26900563fb9655f6789 Mon Sep 17 00:00:00 2001 From: aereal Date: Mon, 17 Nov 2025 20:32:03 +0900 Subject: [PATCH] feat: add seq.Pairwise() --- seq/seq.go | 25 +++++++++++++++++++++++++ seq/seq_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/seq/seq.go b/seq/seq.go index 2f263df..cf2dc7a 100644 --- a/seq/seq.go +++ b/seq/seq.go @@ -195,3 +195,28 @@ func FlatMap[T any, R any](s iter.Seq[T], f func(T) iter.Seq[R]) iter.Seq[R] { } } } + +// Pairwise returns an iterator over consecutive pairs of elements. +// For example, [a, b, c, d] yields [(a, b), (b, c), (c, d)]. +func Pairwise[T any](s iter.Seq[T]) iter.Seq2[T, T] { + return func(yield func(T, T) bool) { + next, stop := iter.Pull(s) + defer stop() + + prev, ok := next() + if !ok { + return + } + + for { + current, ok := next() + if !ok { + return + } + if !yield(prev, current) { + return + } + prev = current + } + } +} diff --git a/seq/seq_test.go b/seq/seq_test.go index abcef0d..2d8a765 100644 --- a/seq/seq_test.go +++ b/seq/seq_test.go @@ -333,6 +333,50 @@ func TestFlatMap(t *testing.T) { } } +func TestPairwise(t *testing.T) { + testCases := []struct { + name string + input []string + want []pair[string, string] + }{ + { + name: "empty", + input: []string{}, + want: []pair[string, string]{}, + }, + { + name: "only one element", + input: []string{"a"}, + want: []pair[string, string]{}, + }, + { + name: "ok", + input: []string{"a", "b", "c", "d"}, + want: []pair[string, string]{ + {"a", "b"}, + {"b", "c"}, + {"c", "d"}, + }, + }, + { + name: "3 elements", + input: []string{"a", "b", "c"}, + want: []pair[string, string]{ + {"a", "b"}, + {"b", "c"}, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := pairs(seq.Pairwise(slices.Values(tc.input))) + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("result mismatch:\n\twant: %#v\n\t got: %#v", tc.want, got) + } + }) + } +} + func list[T any](xs ...T) iter.Seq[T] { return func(yield func(T) bool) { for _, x := range xs {