mirror of
https://github.com/MontFerret/ferret.git
synced 2024-12-14 11:23:02 +02:00
Feature/#10 zip (#113)
* added prototype of ZIP function * add unit test for ZIP function * change comment for ZIP function * added some new tests * small change in unit tests * added ZIP function
This commit is contained in:
parent
446ce3ead5
commit
5d0d9ec537
@ -8,5 +8,6 @@ func NewLib() map[string]core.Function {
|
|||||||
"KEYS": Keys,
|
"KEYS": Keys,
|
||||||
"KEEP": Keep,
|
"KEEP": Keep,
|
||||||
"MERGE": Merge,
|
"MERGE": Merge,
|
||||||
|
"ZIP": Zip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
83
pkg/stdlib/objects/zip.go
Normal file
83
pkg/stdlib/objects/zip.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns an object assembled from the separate parameters keys and values.
|
||||||
|
* Keys and values must be arrays and have the same length.
|
||||||
|
* @params keys (Array of Strings) - an array of strings, to be used as key names in the result.
|
||||||
|
* @params values (Array of Objects) - an array of core.Value, to be used as key values.
|
||||||
|
* @returns (Object) - an object with the keys and values assembled.
|
||||||
|
*/
|
||||||
|
func Zip(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||||
|
err := core.ValidateArgs(args, 2, 2)
|
||||||
|
if err != nil {
|
||||||
|
return values.None, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, arg := range args {
|
||||||
|
if err = core.ValidateType(arg, core.ArrayType); err != nil {
|
||||||
|
return values.None, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := args[0].(*values.Array)
|
||||||
|
vals := args[1].(*values.Array)
|
||||||
|
|
||||||
|
if keys.Length() != vals.Length() {
|
||||||
|
return values.None, core.Error(
|
||||||
|
core.ErrInvalidArgument,
|
||||||
|
fmt.Sprintf("keys and values must have the same length. got keys: %d, values: %d",
|
||||||
|
keys.Length(), vals.Length(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validateArrayOf(core.StringType, keys)
|
||||||
|
if err != nil {
|
||||||
|
return values.None, err
|
||||||
|
}
|
||||||
|
|
||||||
|
zipped := values.NewObject()
|
||||||
|
|
||||||
|
var k values.String
|
||||||
|
var val core.Value
|
||||||
|
var exists bool
|
||||||
|
keyExists := map[values.String]bool{}
|
||||||
|
|
||||||
|
keys.ForEach(func(key core.Value, idx int) bool {
|
||||||
|
k = key.(values.String)
|
||||||
|
|
||||||
|
// this is necessary to impelement ArangoDB's behavior.
|
||||||
|
// in ArangoDB the first value in values is
|
||||||
|
// associated with each key. Ex.:
|
||||||
|
// -- query --
|
||||||
|
// > RETURN ZIP(
|
||||||
|
// > ["a", "b", "a"], [1, 2, 3]
|
||||||
|
// > )
|
||||||
|
// -- result --
|
||||||
|
// > [{"a": 1,"b": 2}]
|
||||||
|
if _, exists = keyExists[k]; exists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
keyExists[k] = true
|
||||||
|
|
||||||
|
val = vals.Get(values.NewInt(idx))
|
||||||
|
|
||||||
|
if values.IsCloneable(val) {
|
||||||
|
val = val.(core.Cloneable).Clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
zipped.Set(k, val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return zipped, nil
|
||||||
|
}
|
133
pkg/stdlib/objects/zip_test.go
Normal file
133
pkg/stdlib/objects/zip_test.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package objects_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
|
"github.com/MontFerret/ferret/pkg/stdlib/objects"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestZip(t *testing.T) {
|
||||||
|
Convey("Invalid arguments", t, func() {
|
||||||
|
Convey("When there are no arguments", func() {
|
||||||
|
actual, err := objects.Zip(context.Background())
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("When single argument", func() {
|
||||||
|
actual, err := objects.Zip(context.Background(), values.NewArray(0))
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
|
||||||
|
actual, err = objects.Zip(context.Background(), values.NewInt(0))
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("When too many arguments", func() {
|
||||||
|
actual, err := objects.Zip(context.Background(),
|
||||||
|
values.NewArray(0), values.NewArray(0), values.NewArray(0))
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("When there is not array argument", func() {
|
||||||
|
actual, err := objects.Zip(context.Background(), values.NewArray(0), values.NewInt(0))
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
|
||||||
|
actual, err = objects.Zip(context.Background(), values.NewInt(0), values.NewArray(0))
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("When there is not string element into keys array", func() {
|
||||||
|
keys := values.NewArrayWith(values.NewInt(0))
|
||||||
|
vals := values.NewArrayWith(values.NewString("v1"))
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
actual, err := objects.Zip(context.Background(), keys, vals)
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("When 1 key and 0 values", func() {
|
||||||
|
keys := values.NewArrayWith(values.NewString("k1"))
|
||||||
|
vals := values.NewArray(0)
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
actual, err := objects.Zip(context.Background(), keys, vals)
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("When 0 keys and 1 values", func() {
|
||||||
|
keys := values.NewArray(0)
|
||||||
|
vals := values.NewArrayWith(values.NewString("v1"))
|
||||||
|
expected := values.None
|
||||||
|
|
||||||
|
actual, err := objects.Zip(context.Background(), keys, vals)
|
||||||
|
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Zip 2 keys and 2 values", t, func() {
|
||||||
|
keys := values.NewArrayWith(
|
||||||
|
values.NewString("k1"),
|
||||||
|
values.NewString("k2"),
|
||||||
|
)
|
||||||
|
vals := values.NewArrayWith(
|
||||||
|
values.NewString("v1"),
|
||||||
|
values.NewInt(2),
|
||||||
|
)
|
||||||
|
expected := values.NewObjectWith(
|
||||||
|
values.NewObjectProperty("k1", values.NewString("v1")),
|
||||||
|
values.NewObjectProperty("k2", values.NewInt(2)),
|
||||||
|
)
|
||||||
|
|
||||||
|
actual, err := objects.Zip(context.Background(), keys, vals)
|
||||||
|
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Zip 3 keys and 3 values. 1 key repeats", t, func() {
|
||||||
|
keys := values.NewArrayWith(
|
||||||
|
values.NewString("k1"),
|
||||||
|
values.NewString("k2"),
|
||||||
|
values.NewString("k1"),
|
||||||
|
)
|
||||||
|
vals := values.NewArrayWith(
|
||||||
|
values.NewInt(1),
|
||||||
|
values.NewInt(2),
|
||||||
|
values.NewInt(3),
|
||||||
|
)
|
||||||
|
expected := values.NewObjectWith(
|
||||||
|
values.NewObjectProperty("k1", values.NewInt(1)),
|
||||||
|
values.NewObjectProperty("k2", values.NewInt(2)),
|
||||||
|
)
|
||||||
|
|
||||||
|
actual, err := objects.Zip(context.Background(), keys, vals)
|
||||||
|
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(actual.Compare(expected), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user