1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

feat: A more reasonable IndexOf function (#66)

This commit is contained in:
Mickls
2022-12-09 11:31:40 +08:00
committed by GitHub
parent 3189628d54
commit d59259bbe0
2 changed files with 74 additions and 5 deletions

View File

@@ -14,6 +14,13 @@ import (
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// Create a static variable to store the hash table.
// This variable has the same lifetime as the entire program and can be shared by functions that are called more than once.
var (
memoryHashMap = make(map[string]map[any]int)
memoryHashCounter = make(map[string]int)
)
// Contain check if the target value is in the slice or not
func Contain[T comparable](slice []T, target T) bool {
for _, item := range slice {
@@ -832,14 +839,44 @@ func Without[T comparable](slice []T, items ...T) []T {
return result
}
// IndexOf returns the index at which the first occurrence of a item is found in a slice or return -1 if the item cannot be found.
func IndexOf[T comparable](slice []T, item T) int {
for i, v := range slice {
if v == item {
return i
// IndexOf returns the index at which the first occurrence of an item is found in a slice or return -1 if the item cannot be found.
func IndexOf[T comparable](arr []T, val T) int {
limit := 10
// gets the hash value of the array as the key of the hash table.
key := fmt.Sprintf("%p", arr)
// determines whether the hash table is empty. If so, the hash table is created.
if memoryHashMap[key] == nil {
memoryHashMap[key] = make(map[any]int)
// iterate through the array, adding the value and index of each element to the hash table.
for i := len(arr) - 1; i >= 0; i-- {
memoryHashMap[key][arr[i]] = i
}
}
// update the hash table counter.
memoryHashCounter[key]++
// use the hash table to find the specified value. If found, the index is returned.
if index, ok := memoryHashMap[key][val]; ok {
// calculate the memory usage of the hash table.
size := len(memoryHashMap)
// If the memory usage of the hash table exceeds the memory limit, the hash table with the lowest counter is cleared.
if size > limit {
var minKey string
var minVal int
for k, v := range memoryHashCounter {
if k == key {
continue
}
if minVal == 0 || v < minVal {
minKey = k
minVal = v
}
}
delete(memoryHashMap, minKey)
delete(memoryHashCounter, minKey)
}
return index
}
return -1
}

View File

@@ -1,6 +1,7 @@
package slice
import (
"fmt"
"math"
"testing"
@@ -669,8 +670,39 @@ func TestIndexOf(t *testing.T) {
assert := internal.NewAssert(t, "TestIndexOf")
arr := []string{"a", "a", "b", "c"}
key := fmt.Sprintf("%p", arr)
assert.Equal(0, IndexOf(arr, "a"))
assert.Equal(-1, IndexOf(arr, "d"))
assert.Equal(2, memoryHashCounter[key])
arr1 := []int{1, 2, 3, 4, 5}
key1 := fmt.Sprintf("%p", arr1)
assert.Equal(3, IndexOf(arr1, 4))
assert.Equal(-1, IndexOf(arr1, 6))
assert.Equal(2, memoryHashCounter[key1])
arr2 := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
key2 := fmt.Sprintf("%p", arr2)
assert.Equal(2, IndexOf(arr2, 3.3))
assert.Equal(3, IndexOf(arr2, 4.4))
assert.Equal(-1, IndexOf(arr2, 6.6))
assert.Equal(3, memoryHashCounter[key2])
for i := 0; i < 6; i++ {
a := []string{"a", "b", "c"}
IndexOf(a, "a")
IndexOf(a, "b")
}
minArr := []string{"c", "b", "a"}
minKey := fmt.Sprintf("%p", minArr)
assert.Equal(0, IndexOf(minArr, "c"))
arr3 := []string{"q", "w", "e"}
key3 := fmt.Sprintf("%p", arr3)
assert.Equal(1, IndexOf(arr3, "w"))
assert.Equal(-1, IndexOf(arr3, "r"))
assert.Equal(2, memoryHashCounter[key3])
assert.Equal(0, memoryHashCounter[minKey])
}
func TestLastIndexOf(t *testing.T) {