Passed
Pull Request — master (#66)
by Hayrullah
56s
created

internal/find_last.go   A

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 49
dl 0
loc 85
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
B internal.baseFindIndex 0 21 6
A internal.FindLastByFromIndex 0 11 3
A internal.findLastIndex 0 12 3
A internal.max 0 5 2
A internal.FindLastBy 0 2 1
A internal.min 0 5 2
1
package internal
2
3
import (
4
	"reflect"
5
6
	"github.com/gotilty/gotil/internal/errs"
7
)
8
9
// FindLastBy iterates over elements of collection, returns an object of lastest element predicate if returns true for.
10
// 		data := []int64{-100, -5, 30, 100}
11
// 		newData, _ := FindLastBy(data, func(val interface{}, i int) bool {
12
// 			if val.(int64) == 30 {
13
// 				return true
14
// 			} else {
15
// 				return false
16
// 			}
17
// 		})
18
// 		// Output: 30
19
func FindLastBy(a interface{}, f func(val interface{}, i int) bool) (interface{}, error) {
20
	return FindLastByFromIndex(a, f, 0)
21
}
22
23
// FindLastBy iterates over elements of collection, returns an object of lastest element predicate if returns true for.
24
// It works same as FindLastBy just from parameter provides to set start index of given slice or array.
25
func FindLastByFromIndex(a interface{}, f func(val interface{}, i int) bool, from int) (interface{}, error) {
26
	val := reflect.ValueOf(a)
27
	switch val.Kind() {
28
	case reflect.Slice, reflect.Array:
29
		index := findLastIndex(val, f, 0)
30
		if index > -1 {
31
			return val.Index(index).Interface(), nil
32
		}
33
		return nil, nil
34
	}
35
	return nil, errs.NewUnsupportedTypeError(val.Kind().String())
36
}
37
38
func findLastIndex(val reflect.Value, f func(val interface{}, i int) bool, from int) int {
39
	length := val.Len()
40
	if length == 0 {
41
		return -1
42
	}
43
	index := length - 1
44
	if from < 0 {
45
		index = max(length+index, 0)
46
	} else {
47
		index = min(index, length-1)
48
	}
49
	return baseFindIndex(val, f, index, true)
50
}
51
52
func baseFindIndex(val reflect.Value, f func(val interface{}, i int) bool, from int, right bool) int {
53
	length := val.Len()
54
	index := from
55
	if right {
56
		for index < length {
57
			value := val.Index(index)
58
			if f(value.Interface(), index) {
59
				return index
60
			}
61
			index--
62
		}
63
	} else {
64
		for index < length {
65
			value := val.Index(index)
66
			if f(value.Interface(), index) {
67
				return index
68
			}
69
			index++
70
		}
71
	}
72
	return -1
73
}
74
75
func max(a, b int) int {
76
	if a > b {
77
		return a
78
	}
79
	return b
80
}
81
func min(a, b int) int {
82
	if a < b {
83
		return a
84
	}
85
	return b
86
}
87