1package funk
2
3import (
4	"reflect"
5)
6
7// Compact creates a slice with all empty/zero values removed.
8func Compact(value interface{}) interface{} {
9	arr := redirectValue(reflect.ValueOf(value))
10
11	if arr.Kind() != reflect.Slice && arr.Kind() != reflect.Array {
12		panic("First parameter must be array or slice")
13	}
14
15	sliceElemType := sliceElem(arr.Type())
16	resultSliceType := reflect.SliceOf(sliceElemType)
17	result := reflect.MakeSlice(resultSliceType, 0, 0)
18
19	for i := 0; i < arr.Len(); i++ {
20		elemVal := arr.Index(i)
21
22		if elemVal.Kind() == reflect.Interface {
23			elemVal = elemVal.Elem()
24		}
25
26		redirectedElemVal := redirectValue(elemVal)
27
28		switch redirectedElemVal.Kind() {
29		case reflect.Invalid:
30			continue
31		case reflect.Func:
32			if redirectedElemVal.IsNil() {
33				continue
34			}
35		case reflect.Map, reflect.Slice, reflect.Chan:
36			if redirectedElemVal.Len() == 0 {
37				continue
38			}
39		default:
40			defaultValue := reflect.Zero(redirectedElemVal.Type()).Interface()
41			if redirectedElemVal.Interface() == defaultValue {
42				continue
43			}
44		}
45
46		result = reflect.Append(result, elemVal)
47	}
48
49	return result.Interface()
50}
51