thoas / go-funk Goto Github PK
View Code? Open in Web Editor NEWA modern Go utility library which provides helpers (map, find, contains, filter, ...)
License: MIT License
A modern Go utility library which provides helpers (map, find, contains, filter, ...)
License: MIT License
Please clarify what is meant by pinging the author on Twitter.
I'm running into an issue when using Get()
with a zero-value or empty slice of structs.
Here's an example:
package main
import (
"fmt"
"log"
"github.com/thoas/go-funk"
)
type BigThing struct {
Littles []LittleThing
}
type LittleThing struct {
SomeKey string
}
func main() {
// Using a zero-value slice (unexpected output)
var x BigThing
iKeys := funk.Get(x.Littles, "SomeKey")
if _, ok := iKeys.([]string); ok {
log.Fatalf("Uh oh...")
}
fmt.Printf("iKeys is %T, not []string\n", iKeys)
// Using an empty slice (unexpected output)
x.Littles = []LittleThing{}
iKeys = funk.Get(x.Littles, "SomeKey")
if _, ok := iKeys.([]string); ok {
log.Fatalf("Uh oh...")
}
fmt.Printf("iKeys is %T, not []string\n", iKeys)
// Using a non-empty slice (expected output)
x.Littles = []LittleThing{{SomeKey: "hello"}}
iKeys = funk.Get(x.Littles, "SomeKey")
keys, ok := iKeys.([]string)
if !ok {
log.Fatalf("Uh oh...")
}
fmt.Println(keys)
}
I expected all three cases to return a zero-value []string
(i.e., a typed nil
), however the first two return an untyped nil
, which causes these type conversions to fail.
Hi @thoas
have time to add #Any and #All functions?
it would be great if supports structs too.
like find out if a user in a slice has a admin field true.
thanks
Hi I would like to use Reduce function but it seems that output result must be always float64, so no Map or Array or whatever else is supported? I am completely new to Go maybe I am missing something. Thank you for your help.
This is a minor feature request. I love the library and would love to see support for go modules as well as well better versioning.
This is how the library loads within my project when I use go modules. This makes it harder to depend on stable versions of the library.
module github.com/syncaide/gate
require (
...
github.com/thoas/go-funk v0.0.0-20190407194523-c43409e2d5de
...
)
With go.mod being added and a more golang compliant versioning scheme the dependency would end up looking as follows. This is much more dependable if in the future there are breaking changes introduced into the application.
module github.com/syncaide/gate
require (
...
github.com/thoas/go-funk v0.4.0
...
)
Hi,
When using funk.Get(make([]*Xxxxx, 0), "Aaaa.Bbbbb")
I get this panic:
panic: reflect: call of reflect.Value.Type on zero Value
goroutine 1 [running]:
reflect.Value.Type(0x0, 0x0, 0x0, 0x0, 0x9f34c0)
/usr/local/go/src/reflect/value.go:1743 +0x16c
github.com/thoas/go-funk.get(0xa0e300, 0xc000474cc0, 0x197, 0xb66d75, 0xb, 0x197, 0x2, 0xae7d00)
/home/aaaaaaa/vendor/github.com/thoas/go-funk/retrieve.go:46 +0x289
github.com/thoas/go-funk.get(0x9f34c0, 0xc000474cc0, 0x16, 0xb66d75, 0xe, 0xa37000, 0xb8d968, 0x13)
/home/aaaaaaa/vendor/github.com/thoas/go-funk/retrieve.go:69 +0x4b2
github.com/thoas/go-funk.Get(0x9f34c0, 0xc000474cc0, 0xb66d75, 0xe, 0xc0002d1700, 0x76e4da)
/home/aaaaaaa/vendor/github.com/thoas/go-funk/retrieve.go:10 +0xbe
It's related to:
https://github.com/thoas/go-funk/blob/master/retrieve.go#L45-L48
I don't understand exactly why this is happening. I can for sure make a statement my array is not empty before using funk.Get
, but maybe funk should return me an empty array?
Thanks,
The indirect
function becomes handy whenever I worked with reflection.
func indirect(a interface{}) interface{} {
s := []string{"1","2"}
if inStringSliceByIndex(s, 1){
}
func ArrayToObj(field string, arr interface{}) map[string]interface{} {
var result = map[string]interface{}{}
var arrValue = reflect.ValueOf(arr) // convert to reflect.Value
var arrFirstValField = arrValue.Index(0).FieldByName(field)
if arrValue.Len() == 0 {
return result
}
if arrFirstValField.Kind() == reflect.String {
for i := 0; i < arrValue.Len(); i++ {
var item = arrValue.Index(i).Interface()
var id = arrValue.Index(i).FieldByName(field).Interface().(string)
result[id] = item
}
}
if arrFirstValField.Kind() == reflect.Int {
for i := 0; i < arrValue.Len(); i++ {
var item = arrValue.Index(i).Interface()
id := strconv.Itoa(arrValue.Index(i).FieldByName(field).Interface().(int) )
result[id] = item
}
}
if arrFirstValField.Kind() == reflect.Int64 {
for i := 0; i < arrValue.Len(); i++ {
var item = arrValue.Index(i).Interface()
var idn = arrValue.Index(i).FieldByName(field).Interface().(int64)
id := strconv.FormatInt(idn, 10)
result[id] = item
}
}
return result
}
The package is missing a go.mod file
Hi! I was browsing through the code, and for the Uniq
function I noticed this line:
Line 328 in 1d24b29
Now, the code value.Index(j).Set(val)
is actively editing the input argument. Could you help me understand why this line exists/does what it does? I'm failing to grasp the logic behind it 😅
Edit: A coffee helped. I understand the algorithm itself, it edits the input argument and a copy is therefore not needed, using j
as a secondary index. Though, there is no mention in the comment/function doc (unless I missed it somewhere), that it actually alters the original array! Maybe this issue is more related to this, I was not understanding why the input argument was being altered.
Thanks a lot,
Alberto
It would be great if everywhere an iteratee was needed (i.e. IsIteratee(i) must be true) it also accepted a pointer to such iteratee. It's a less frequent but very useful use case.
Example use case: input is a reflect type and JSON which encodes a slice of the given type. Create a pointer to a slice of the given type dynamically, use json.Unmarshal to populate it. At this point it would be great to be able to use funk.Map directly instead of having to use reflect to dereference the pointer like this reflect.ValueOf(slicePtr).Elem().Interface(), after all that's the whole point of funk, to simplify the code that deals with various Go data structures.
Code example https://goplay.space/#0GUn6UbxvJR (see locally defined Map).
Not sure what's the best way to implement this within funk, maybe GetIteratee instead of IsIteratee to hide the code dealing with dereferencing the pointer?
If there is an agreed upon way to do it I would probably be able to submit PR.
Is there any reason why there are no uint
typed functions in typesafe.go
looks to me these functions should be there.
If I use Find
function, I'll get a object. If I use IndexOf
function, the predicate function will not work.
So I want the lib support FindIndex
or something like that would help me to find a object with its index. Thank you so much
I was curious what the performance impact is of your functional implementation vs the classic implementations. I haven't gone in depth, but the results are interesting (in particular the memory allocations for Contains
.)
➜ funk-bench git:(master) ✗ go test -benchmem -bench .
testing: warning: no tests to run
BenchmarkContains/Idiomatic-8 1000 1946239 ns/op 0 B/op 0 allocs/op
BenchmarkContains/funk-8 2 645429814 ns/op 28916552 B/op 3614564 allocs/op
PASS
ok github.com/christian-blades-cb/funk-bench 4.417s
Merge 2 map:
a := map[string]string{
"hello": "world",
"foo": "bar",
}
b := map[string]string{
"key": "value",
"foo": "BAR",
}
funk.Union(a, b)
Returning:
map[string]string{
"hello": "world",
"foo": "BAR",
"key": "value",
}
There is no checks on Chunk's size is set to 0. Does it should return N empty arrays where N is len of the input? Or just empty array?
Hello,
When trying following codes:
package main
import (
"github.com/davecgh/go-spew/spew"
"github.com/thoas/go-funk"
)
type Foo struct {
Sth interface{}
}
type User struct {
Phone struct {
CountryCode string
Number int
}
Age int
}
func main() {
e := Foo{
Sth: User{
Phone: struct {
CountryCode string
Number int
}{CountryCode: "+1", Number: 123},
Age: 10,
},
}
spew.Dump(funk.Get(e, "Sth.Age"))
spew.Dump(funk.Get(e, "Sth.Phone.Number"))
spew.Dump(funk.Get(e, "Sth.Phone.CountryCode"))
}
What I expect to get is:
(int) 10
(int) 123
(string) (len=2) "+1"
But actually I get 3 repeated
(main.User) {
Phone: (struct { CountryCode string; Number int }) {
CountryCode: (string) (len=2) "+1",
Number: (int) 123
},
Age: (int) 10
}
The reason looks like, Foo.Sth is interface type and redirectValue doesn't handle this, I try to fix it with this change:
- if !value.IsValid() || value.Kind() != reflect.Ptr {
+ if !value.IsValid() || (value.Kind() != reflect.Ptr && value.Kind() != reflect.Interface) {
return value
}
- res := reflect.Indirect(value)
+ res := value.Elem()
It works and all tests pass, but not sure if other things will be broken. If the change do work correctly, could you please apply it(or me send a PR)? Thanks.
Hi,
Inside the Filter method, I need to compare with a param defined outside anonymous method funk.Filter.
for _, repartition := range repartitions {
operationsGroupByRepartition := funk.Filter(operations, func(operation models.OperationFromMetadata) bool {
return operation.Repartition == repartition.Name()
}).([]models.OperationFromMetadata)
}
so repartition is nil
.
Is there anything I could do about it ?
Is there any way I can use funck.Groupby?
I think it can be great to have the possibility to easily chains several funk methods through a builder, like Lodash
.
I can try to implement this features if you want.
It seems that TestChainShuffle
and TestSubtract
sometimes fail. This can be reproduced with go test . -count=100
and such.
--- FAIL: TestChainShuffle (0.00s)
--- FAIL: TestChainShuffle/test_case_#1 (0.00s)
chain_builder_test.go:326:
Error Trace: chain_builder_test.go:326
Error: Should not be: []int{1, 3, 2, 4, 0}
Test: TestChainShuffle/test_case_#1
--- FAIL: TestSubtract (0.00s)
subtraction_test.go:16:
Error Trace: subtraction_test.go:16
Error: Not equal:
expected: []string{"hello", "hi"}
actual : []string{"hi", "hello"}
Diff:
--- Expected
+++ Actual
@@ -1,4 +1,4 @@
([]string) (len=2) {
- (string) (len=5) "hello",
- (string) (len=2) "hi"
+ (string) (len=2) "hi",
+ (string) (len=5) "hello"
}
Test: TestSubtract
funk.If(condition, true, false)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.