github.com/kazu/loncha@v0.6.3/uniq.go (about) 1 // Copyright 2019 Kazuhisa TAKEI<xtakei@rytr.jp>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package DeDuplication for slice. 6 // 7 // To Find from slice: (list is slice) 8 // loncha.Uniq(&list, func(i,j int) { 9 // return list[i].ID == list[j].ID 10 //} 11 12 package loncha 13 14 import ( 15 "reflect" 16 "sort" 17 ) 18 19 type IdentFn func(i int) interface{} 20 21 // Uniq is deduplicate using fn . if slice is not pointer of slice or empty, return error 22 func Uniq(slice interface{}, fn IdentFn) error { 23 24 pRv, err := slice2Reflect(slice) 25 if err != nil { 26 return err 27 } 28 n := pRv.Elem().Len() 29 30 exists := make(map[interface{}]bool, n) 31 32 err = OldFilter(slice, func(i int) bool { 33 if !exists[fn(i)] { 34 exists[fn(i)] = true 35 return true 36 } 37 return false 38 }) 39 exists = nil 40 return err 41 } 42 43 // Uniq2 is deduplicate using fn . if slice is not pointer of slice or empty, return error 44 func Uniq2(slice interface{}, fn CompareFunc) error { 45 46 pRv, err := slice2Reflect(slice) 47 if err != nil { 48 return err 49 } 50 n := pRv.Elem().Len() 51 52 swap := reflect.Swapper(pRv.Elem().Interface()) 53 54 uniqCnt := int(1) 55 56 for i := 0; i < n; i++ { 57 for j := 0; j < uniqCnt; j++ { 58 if fn(i, j) { 59 goto SKIP 60 } 61 } 62 swap(uniqCnt, i) 63 uniqCnt++ 64 SKIP: 65 } 66 pRv.Elem().SetLen(uniqCnt) 67 68 return err 69 } 70 71 // UniqWithSort is deduplicating using fn, sorting before dedup. if slice is not pointer of slice or empty, return error 72 func UniqWithSort(slice interface{}, fn CompareFunc) (int, error) { 73 74 pRv, err := slice2Reflect(slice) 75 if err != nil { 76 return -1, err 77 } 78 n := pRv.Elem().Len() 79 80 if !sort.SliceIsSorted(pRv.Elem().Interface(), fn) { 81 sort.Slice(pRv.Elem().Interface(), fn) 82 } 83 swap := reflect.Swapper(pRv.Elem().Interface()) 84 85 a, b := 0, 1 86 for b < n { 87 if fn(a, b) { 88 a++ 89 if a != b { 90 swap(a, b) 91 } 92 } 93 b++ 94 } 95 return a + 1, nil 96 97 }