Skip to content

Commit

Permalink
add function FindMatchingPairs
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan O'Hara-Reid committed May 2, 2024
1 parent 44d50a3 commit 3dd9e53
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
33 changes: 33 additions & 0 deletions currency/pairs.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,36 @@ func (p Pairs) GetPairsByBase(baseTerm Code) (Pairs, error) {
}
return pairs, nil
}

// equalKey is a small key for testing pair equality without delimiter
type equalKey struct {
Base *Item
Quote *Item
}

// FindMatchingPairs returns all pairs that match the incoming pairs.
// Duplications are intentionally removed.
func (p Pairs) FindMatchingPairs(b Pairs) Pairs {
if len(p) == 0 || len(b) == 0 {
return []Pair{}
}
m := map[equalKey]struct{}{}
for i := range p {
m[equalKey{Base: p[i].Base.Item, Quote: p[i].Quote.Item}] = struct{}{}
}
outgoing := func() Pairs {
if len(p) < len(b) {
return make(Pairs, 0, len(p))
} else {

Check warning on line 504 in currency/pairs.go

View workflow job for this annotation

GitHub Actions / lint

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
return make(Pairs, 0, len(b))
}
}()
for i := range b {
key := equalKey{Base: b[i].Base.Item, Quote: b[i].Quote.Item}
if _, ok := m[key]; ok {
outgoing = append(outgoing, b[i])
delete(m, key)
}
}
return outgoing
}
58 changes: 58 additions & 0 deletions currency/pairs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package currency
import (
"encoding/json"
"errors"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -870,3 +871,60 @@ func TestGetPairsByBase(t *testing.T) {
t.Fatalf("received: '%v' but expected '%v'", len(got), 3)
}
}

func TestFindMatchingPairs(t *testing.T) {
t.Parallel()

available := Pairs{
NewPair(BTC, USD),
NewPair(LTC, USD),
NewPair(USD, NZD),
NewPair(LTC, USDT),
NewPair(LTC, DAI),
NewPair(USDT, XRP),
NewPair(DAI, XRP),
NewPair(DAI, XRP), // duplication
}

testCases := []struct {
incoming Pairs
expected Pairs
}{
{incoming: Pairs{NewPair(BTC, USD)}, expected: Pairs{NewPair(BTC, USD)}},
{incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD)}},
{incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD)}},
{incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT)}},
{incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI)}},
{incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP)}},
{incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP)}},
/*test for pair not available*/ {incoming: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP), NewPair(WABI, MAD)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP)}},
/*test for duplication*/ {incoming: Pairs{NewPair(BTC, USD), NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP), NewPair(WABI, MAD)}, expected: Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP)}},
}

for x := range testCases {
tc := testCases[x]
t.Run(fmt.Sprintf("Test %d", x), func(t *testing.T) {
t.Parallel()
require.Equal(t, tc.expected, available.FindMatchingPairs(tc.incoming))
})
}
}

// 2482711 438.9 ns/op 352 B/op 1 allocs/op
func BenchmarkFindMatchingPairs(b *testing.B) {
available := Pairs{
NewPair(BTC, USD),
NewPair(LTC, USD),
NewPair(USD, NZD),
NewPair(LTC, USDT),
NewPair(LTC, DAI),
NewPair(USDT, XRP),
NewPair(DAI, XRP),
}

other := Pairs{NewPair(BTC, USD), NewPair(LTC, USD), NewPair(USD, NZD), NewPair(LTC, USDT), NewPair(LTC, DAI), NewPair(USDT, XRP), NewPair(DAI, XRP)}

for x := 0; x < b.N; x++ {
_ = available.FindMatchingPairs(other)
}
}

0 comments on commit 3dd9e53

Please sign in to comment.