github.com/kazu/loncha@v0.6.3/loncha_test.go (about)

     1  package loncha
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"math/rand"
     7  	"sort"
     8  	"testing"
     9  
    10  	"github.com/thoas/go-funk"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  type Element struct {
    16  	ID   int
    17  	Name string
    18  }
    19  
    20  const (
    21  	CREATE_SLICE_MAX int = 10000
    22  )
    23  
    24  func MakeSliceSample() (slice []Element) {
    25  	slice = make([]Element, 0, CREATE_SLICE_MAX*2)
    26  
    27  	for i := 0; i < CREATE_SLICE_MAX; i++ {
    28  		slice = append(slice,
    29  			Element{
    30  				ID:   int(math.Abs(float64(rand.Intn(CREATE_SLICE_MAX)))),
    31  				Name: fmt.Sprintf("aaa%d", i),
    32  			})
    33  	}
    34  	return
    35  }
    36  
    37  type Elements []Element
    38  type PtrElements []*Element
    39  
    40  type EqInt map[string]int
    41  type EqString map[string]string
    42  
    43  type Eq map[string]interface{}
    44  
    45  func (eq EqInt) Func(slice Elements) (funcs []CondFunc) {
    46  	funcs = make([]CondFunc, 0, len(eq))
    47  	for key, _ := range eq {
    48  		switch key {
    49  		case "ID":
    50  			fn := func(i int) bool {
    51  				return slice[i].ID == eq[key]
    52  			}
    53  			funcs = append(funcs, fn)
    54  		}
    55  	}
    56  	return
    57  }
    58  
    59  func (eq EqString) Func(slice Elements) (funcs []CondFunc) {
    60  	funcs = make([]CondFunc, 0, len(eq))
    61  	for key, _ := range eq {
    62  		switch key {
    63  		case "Name":
    64  			fn := func(i int) bool {
    65  				return slice[i].Name == eq[key]
    66  			}
    67  			funcs = append(funcs, fn)
    68  		}
    69  	}
    70  	return
    71  }
    72  
    73  func (slice Elements) Where(q Eq) Elements {
    74  	eqInt := make(EqInt)
    75  	eqString := make(EqString)
    76  	funcs := make([]CondFunc, 0, len(q))
    77  	for key, value := range q {
    78  		switch key {
    79  		case "ID":
    80  			eqInt[key] = value.(int)
    81  			funcs = append(funcs, eqInt.Func(slice)[0])
    82  		case "Name":
    83  			eqString[key] = value.(string)
    84  			funcs = append(funcs, eqString.Func(slice)[0])
    85  		}
    86  	}
    87  	oslice := &slice
    88  	OldFilter(oslice, funcs...)
    89  	return *oslice
    90  }
    91  
    92  func MakePtrSliceSample() (slice []*Element) {
    93  	slice = make([]*Element, 0, CREATE_SLICE_MAX*2)
    94  
    95  	for i := 0; i < CREATE_SLICE_MAX; i++ {
    96  		slice = append(slice,
    97  			&Element{
    98  				ID:   int(math.Abs(float64(rand.Intn(CREATE_SLICE_MAX)))),
    99  				Name: fmt.Sprintf("aaa%d", i),
   100  			})
   101  	}
   102  	return
   103  }
   104  
   105  func TestWhere(t *testing.T) {
   106  	slice := Elements(MakeSliceSample())
   107  
   108  	nSlice := slice.Where(Eq{"ID": 555})
   109  
   110  	assert.True(t, nSlice[0].ID == 555, nSlice)
   111  	assert.True(t, len(nSlice) < 100, len(nSlice))
   112  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   113  }
   114  
   115  func TestFind(t *testing.T) {
   116  	nSlice := Elements(MakeSliceSample())
   117  	id := nSlice[50].ID
   118  	data, err := Find(&nSlice, func(i int) bool {
   119  		return nSlice[i].ID == id
   120  	})
   121  
   122  	assert.NoError(t, err)
   123  	elm := data.(Element)
   124  	assert.True(t, elm.ID == id, elm)
   125  
   126  	nSlice = MakeSliceSample()
   127  	id = nSlice[50].ID
   128  	data, err = Find(nSlice, func(i int) bool {
   129  		return nSlice[i].ID == id
   130  	})
   131  
   132  	assert.NoError(t, err)
   133  	elm = data.(Element)
   134  	assert.True(t, elm.ID == id, elm)
   135  
   136  }
   137  
   138  func TestLastIndexOf(t *testing.T) {
   139  	nSlice := Elements(MakeSliceSample())
   140  	id := nSlice[50].ID
   141  	i, err := LastIndexOf(nSlice, func(i int) bool {
   142  		return nSlice[i].ID == id
   143  	})
   144  
   145  	assert.NoError(t, err)
   146  	assert.True(t, nSlice[i].ID == id, nSlice[i])
   147  
   148  	nSlice = MakeSliceSample()
   149  	id = nSlice[50].ID
   150  	i, err = LastIndexOf(nSlice, func(i int) bool {
   151  		return nSlice[i].ID == id
   152  	})
   153  
   154  	assert.NoError(t, err)
   155  	assert.True(t, nSlice[i].ID == id, nSlice[i])
   156  
   157  }
   158  
   159  func TestFilter(t *testing.T) {
   160  	nSlice := Elements(MakeSliceSample())
   161  	id := nSlice[50].ID
   162  	OldFilter(&nSlice, func(i int) bool {
   163  		return nSlice[i].ID == id
   164  	})
   165  
   166  	assert.True(t, nSlice[0].ID == id, nSlice)
   167  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   168  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   169  }
   170  
   171  func TestFilter2(t *testing.T) {
   172  	nSlice := Elements(MakeSliceSample())
   173  	id := nSlice[50].ID
   174  	var err error
   175  	nSlice, err = Filter(nSlice, nil,
   176  		Cond2[FilterOpt[Element]](func(obj *Element) bool {
   177  			return obj.ID == id
   178  		}))
   179  
   180  	assert.NoError(t, err)
   181  	assert.True(t, nSlice[0].ID == id, nSlice)
   182  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   183  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   184  
   185  	nSlice = Elements(MakeSliceSample())
   186  	id = nSlice[50].ID
   187  	nSlice, err = Filter(nSlice, nil,
   188  		FilterVersion[FilterOpt[Element]](4),
   189  		Cond2[FilterOpt[Element]](func(obj *Element) bool {
   190  			return obj.ID == id || obj.ID == id+100
   191  		}))
   192  
   193  	assert.NoError(t, err)
   194  	assert.True(t, nSlice[0].ID == id, nSlice)
   195  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   196  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   197  
   198  	nSlice = Elements(MakeSliceSample())
   199  	id = nSlice[50].ID
   200  	expect := nSlice[50]
   201  	nSlice, err = Filter(nSlice, nil,
   202  		FilterVersion[FilterOpt[Element]](3),
   203  		Equal[FilterOpt[Element]](expect))
   204  
   205  	assert.NoError(t, err)
   206  	assert.True(t, nSlice[0].ID == id, nSlice)
   207  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   208  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   209  
   210  	nSlice = Elements(MakeSliceSample())
   211  	id = nSlice[50].ID
   212  	nSlice, err = Filter(nSlice,
   213  		func(obj *Element) bool {
   214  			return obj.ID == id || obj.ID == id+100
   215  		})
   216  
   217  	assert.NoError(t, err)
   218  	assert.True(t, nSlice[0].ID == id, nSlice)
   219  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   220  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   221  
   222  	nSlice = Elements(MakeSliceSample())
   223  	id = nSlice[50].ID
   224  	nSlice, err = Filter(nSlice, nil,
   225  		FilterVersion[FilterOpt[Element]](3),
   226  		Cond2[FilterOpt[Element]](func(obj *Element) bool {
   227  			return obj.ID == id || obj.ID == id+100
   228  		}))
   229  
   230  	assert.NoError(t, err)
   231  	assert.True(t, nSlice[0].ID == id, nSlice)
   232  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   233  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   234  
   235  	nSlice = Elements(MakeSliceSample())
   236  	id = nSlice[50].ID
   237  	nSlice = Filterable(
   238  		func(obj *Element) bool {
   239  			return obj.ID == id || obj.ID == id+100
   240  		})(nSlice)
   241  
   242  	assert.NoError(t, err)
   243  	assert.True(t, nSlice[0].ID == id, nSlice)
   244  	assert.True(t, len(nSlice) < CREATE_SLICE_MAX, len(nSlice))
   245  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   246  
   247  }
   248  
   249  func TestDelete(t *testing.T) {
   250  
   251  	nSlice := Elements(MakeSliceSample())
   252  
   253  	beforeSlice := make(Elements, len(nSlice))
   254  	copy(beforeSlice[:len(nSlice)], nSlice)
   255  	afterSlice := make(Elements, len(nSlice))
   256  
   257  	size := len(nSlice)
   258  	id := nSlice[100].ID
   259  	Delete(&nSlice, func(i int) bool {
   260  		return nSlice[i].ID == id
   261  	})
   262  
   263  	assert.True(t, nSlice[0].ID != 555, nSlice)
   264  	assert.True(t, len(nSlice) < size, len(nSlice))
   265  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   266  
   267  	afterSlice = afterSlice[:len(nSlice)]
   268  	copy(afterSlice[:len(nSlice)], nSlice)
   269  	nSlice = nSlice[:len(beforeSlice)]
   270  	copy(nSlice[:len(beforeSlice)], beforeSlice)
   271  
   272  	size = len(nSlice)
   273  	deleteCond := func(e *Element) bool {
   274  		return e.ID == id
   275  	}
   276  	nSlice = Deletable(deleteCond)(nSlice)
   277  
   278  	assert.Equal(t, afterSlice, nSlice)
   279  
   280  }
   281  
   282  func TestUniq(t *testing.T) {
   283  	nSlice := Elements(MakeSliceSample())
   284  	nSlice = append(nSlice, Element{ID: nSlice[0].ID})
   285  	size := len(nSlice)
   286  
   287  	fn := func(i int) interface{} { return i }
   288  	assert.NotEqual(t, fn(1), fn(2))
   289  	Uniq(&nSlice, func(i int) interface{} {
   290  		return nSlice[i].ID
   291  	})
   292  
   293  	assert.True(t, len(nSlice) < size, len(nSlice))
   294  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   295  }
   296  
   297  func TestUniq2(t *testing.T) {
   298  	nSlice := Elements(MakeSliceSample())
   299  	nSlice = append(nSlice, Element{ID: nSlice[0].ID})
   300  	size := len(nSlice)
   301  	nSlice2 := make([]Element, len(nSlice))
   302  	copy(nSlice2, nSlice)
   303  
   304  	Uniq2(&nSlice, func(i, j int) bool {
   305  		return nSlice[i].ID == nSlice[j].ID
   306  	})
   307  	Uniq(&nSlice2, func(i int) interface{} {
   308  		return nSlice2[i].ID
   309  	})
   310  
   311  	assert.True(t, len(nSlice) < size, len(nSlice))
   312  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   313  	assert.Equal(t, len(nSlice), len(nSlice2))
   314  
   315  }
   316  
   317  func TestUniqWithSort(t *testing.T) {
   318  	nSlice := Elements(MakeSliceSample())
   319  	nSlice = append(nSlice, Element{ID: nSlice[0].ID})
   320  	//size := len(nSlice)
   321  	nSlice2 := make([]Element, len(nSlice))
   322  	copy(nSlice2, nSlice)
   323  
   324  	UniqWithSort(&nSlice, func(i, j int) bool {
   325  		return nSlice[i].ID < nSlice[j].ID
   326  	})
   327  
   328  	//assert.True(t, len(nSlice) < size, len(nSlice))
   329  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   330  	assert.Equal(t, len(nSlice), len(nSlice2))
   331  
   332  }
   333  
   334  func TestSelect(t *testing.T) {
   335  	slice := MakeSliceSample()
   336  
   337  	ret, err := Select(&slice, func(i int) bool {
   338  		return slice[i].ID < 50
   339  	})
   340  	nSlice, ok := ret.([]Element)
   341  
   342  	assert.NoError(t, err)
   343  	assert.True(t, nSlice[0].ID < 50, nSlice)
   344  	assert.True(t, ok)
   345  	assert.True(t, len(nSlice) < 100, len(nSlice))
   346  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   347  
   348  	slice = MakeSliceSample()
   349  
   350  	ret, err = Select(slice, func(i int) bool {
   351  		return slice[i].ID < 50
   352  	})
   353  	nSlice, ok = ret.([]Element)
   354  
   355  	assert.NoError(t, err)
   356  	assert.True(t, nSlice[0].ID < 50, nSlice)
   357  	assert.True(t, ok)
   358  	assert.True(t, len(nSlice) < 100, len(nSlice))
   359  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   360  
   361  	slice = MakeSliceSample()
   362  
   363  	islessID := func(id int) func(e *Element) bool {
   364  		return func(e *Element) bool {
   365  			return e.ID < id
   366  		}
   367  	}
   368  
   369  	nSlice = Selectable(islessID(50))(slice)
   370  
   371  	assert.NoError(t, err)
   372  	assert.True(t, nSlice[0].ID < 50, nSlice)
   373  	assert.True(t, ok)
   374  	assert.True(t, len(nSlice) < 100, len(nSlice))
   375  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   376  
   377  }
   378  
   379  func TestPtrSelect(t *testing.T) {
   380  	slice := MakePtrSliceSample()
   381  
   382  	ret, err := Select(&slice, func(i int) bool {
   383  		return slice[i].ID < 50
   384  	})
   385  	nSlice, ok := ret.([]*Element)
   386  
   387  	assert.NoError(t, err)
   388  	assert.True(t, nSlice[0].ID < 50, nSlice)
   389  	assert.True(t, ok)
   390  	assert.True(t, len(nSlice) < 100, len(nSlice))
   391  	t.Logf("nSlice.len=%d cap=%d\n", len(nSlice), cap(nSlice))
   392  }
   393  
   394  func TestShuffle(t *testing.T) {
   395  	slice := MakeSliceSample()
   396  	a := slice[0]
   397  
   398  	err := Shuffle(slice, 2)
   399  
   400  	assert.NoError(t, err)
   401  	assert.NotEqual(t, slice[0].ID, a.ID)
   402  }
   403  
   404  func TestReverse(t *testing.T) {
   405  	slice := []int{1, 4, 2, 6, 4, 6}
   406  	Reverse(slice)
   407  
   408  	assert.Equal(t, []int{6, 4, 6, 2, 4, 1}, slice)
   409  }
   410  
   411  func TestIntersect(t *testing.T) {
   412  	slice1 := []int{1, 4, 2, 6, 4, 6}
   413  	slice2 := []int{2, 5, 9, 6, 4}
   414  
   415  	result := Intersect(slice1, slice2)
   416  
   417  	assert.Equal(t, []int{2, 6, 4}, result)
   418  }
   419  
   420  func TestIntersectSSorted(t *testing.T) {
   421  	slice1 := []int{6, 4, 2, 1}
   422  	slice2 := []int{9, 6, 5, 3, 2}
   423  	Reverse(slice1)
   424  	Reverse(slice2)
   425  
   426  	result := IntersectSorted(slice1, slice2, func(s []int, i int) int {
   427  		return s[i]
   428  	})
   429  
   430  	assert.Equal(t, []int{2, 6}, result)
   431  }
   432  
   433  func TestSub(t *testing.T) {
   434  	slice1 := []int{6, 4, 2, 1}
   435  	slice2 := []int{9, 6, 5, 3, 2}
   436  	Reverse(slice1)
   437  	Reverse(slice2)
   438  
   439  	result := Sub(slice1, slice2)
   440  
   441  	assert.Equal(t, []int{1, 4}, result)
   442  }
   443  
   444  func TestSubSorted(t *testing.T) {
   445  	slice1 := []int{10, 6, 4, 2}
   446  	slice2 := []int{9, 6, 5, 3, 2, 1}
   447  	Reverse(slice1)
   448  	Reverse(slice2)
   449  
   450  	result := SubSorted(slice1, slice2, func(s []int, i int) int {
   451  		return s[i]
   452  	})
   453  
   454  	assert.Equal(t, []int{4, 10}, result)
   455  }
   456  
   457  type V4sum struct {
   458  	A int
   459  }
   460  
   461  func TestInject(t *testing.T) {
   462  	slice1 := []int{10, 6, 4, 2}
   463  
   464  	sum1 := Inject(slice1, func(sum int, t int) int {
   465  		return sum + t
   466  	})
   467  	assert.Equal(t, 22, sum1)
   468  
   469  	sum := Reduce(slice1, func(sum *int, t int) *int {
   470  		if sum == nil {
   471  			sum = new(int)
   472  			*sum = 0
   473  		}
   474  		v := *sum + t
   475  		return &v
   476  	})
   477  	assert.Equal(t, 22, *sum)
   478  
   479  	sum4 := Sum(slice1)
   480  
   481  	assert.Equal(t, 22, sum4)
   482  
   483  	sum2 := Reducable(func(sum *int, t int) *int {
   484  		if sum == nil {
   485  			sum = new(int)
   486  			*sum = 0
   487  		}
   488  		v := *sum + t
   489  		return &v
   490  	})(slice1)
   491  	assert.Equal(t, *sum, *sum2)
   492  
   493  	d := int(0)
   494  	_ = d
   495  
   496  	sum3 := Reducable(func(sum *int, t int) *int {
   497  		if sum == nil {
   498  			sum = new(int)
   499  			*sum = 0
   500  		}
   501  		v := *sum + t
   502  		return &v
   503  	}, Default(&d))(slice1)
   504  	assert.Equal(t, *sum, *sum3)
   505  
   506  	slice2 := []V4sum{
   507  		{1}, {2},
   508  	}
   509  
   510  	sumFns := SumWithFn(slice2, func(a V4sum) int { return a.A })
   511  	assert.Equal(t, sumFns, 3)
   512  
   513  }
   514  
   515  func TestGettable(t *testing.T) {
   516  
   517  	slice1 := []int{10, 6, 4, 2}
   518  
   519  	r := Gettable(func(v *int) bool { return *v == 4 })(slice1)
   520  
   521  	assert.Equal(t, 4, r)
   522  
   523  }
   524  
   525  func TestConv(t *testing.T) {
   526  	slice1 := []int{10, 6, 4, 2}
   527  
   528  	int64s := Convertable(
   529  		func(i int) (int64, bool) {
   530  			return int64(100 + i), false
   531  		})(slice1)
   532  
   533  	assert.Equal(t, slice1[0]+100, int(int64s[0]))
   534  
   535  }
   536  
   537  func has[T comparable](a T) func(e *T) bool {
   538  	return func(e *T) bool {
   539  		return *e == a
   540  	}
   541  
   542  }
   543  
   544  func TestContain(t *testing.T) {
   545  	slice1 := []int{10, 6, 4, 2}
   546  
   547  	assert.True(t, Containable(has(6))(slice1))
   548  	assert.False(t, Containable(has(11))(slice1))
   549  
   550  	assert.True(t,
   551  		Contain(slice1, func(i int) bool { return slice1[i] == 6 }))
   552  
   553  }
   554  
   555  func TestEvery(t *testing.T) {
   556  	slice1 := []int{10, 6, 4, 2}
   557  
   558  	assert.True(t,
   559  		Every(func(v *int) bool {
   560  			*v = +1
   561  			return true
   562  		})(slice1...))
   563  
   564  	assert.False(t,
   565  		Every(func(v *int) bool {
   566  			*v++
   567  			if *v == 5 {
   568  				return false
   569  			}
   570  			return true
   571  		})(slice1...))
   572  	assert.True(t,
   573  		EveryWithIndex(func(i int, v *int) bool {
   574  			*v = +1
   575  			return true
   576  		})(slice1...))
   577  
   578  }
   579  
   580  func Sort[T Ordered](s []T) []T {
   581  
   582  	sort.Slice(s, func(i, j int) bool {
   583  		return s[i] <= s[j]
   584  	})
   585  
   586  	return s
   587  }
   588  
   589  func TestMap(t *testing.T) {
   590  
   591  	m := map[int]int{
   592  		1: 20,
   593  		4: 30,
   594  	}
   595  	assert.Equal(t, []int{1, 4}, Sort(Keys(m)))
   596  	assert.Nil(t, Keys[int, int](nil))
   597  	assert.Equal(t, []int{20, 30}, Sort(Values(m)))
   598  	assert.Nil(t, Values[int, int](nil))
   599  
   600  	nM := SelectMap(m, func(k, v int) (int, int, bool) {
   601  		if k+v == 34 {
   602  			return k, v, true
   603  		}
   604  		return k + 10, v + 100, false
   605  	})
   606  
   607  	assert.Equal(t, 120, nM[11])
   608  
   609  }
   610  
   611  func TestZipper(t *testing.T) {
   612  
   613  	a := []string{"bob", "hoge", "one", "home"}
   614  	b := []int{0, 1, 2}
   615  
   616  	m := Zipper(ToMap[string, int], map[string]int{})(a, b)
   617  
   618  	assert.Equal(t, 0, m["bob"])
   619  	assert.Equal(t, 2, m["one"])
   620  	assert.Equal(t, 0, m["home"])
   621  
   622  }
   623  
   624  // BenchmarkFilter/loncha.Filter-16         	     100	     89142 ns/op	   82119 B/op	       4 allocs/op
   625  // BenchmarkFilter/loncha.Filter_pointer-16 	     100	       201 ns/op	       0 B/op	       0 allocs/op
   626  // BenchmarkFilter/hand_Filter_pointer-16   	     100	     24432 ns/op	   81921 B/op	       1 allocs/op
   627  // BenchmarkFilter/go-funk.Filter-16        	     100	   2370492 ns/op	  640135 B/op	   20004 allocs/op
   628  // BenchmarkFilter/go-funk.Filter_pointer-16         100	      1048 ns/op	      64 B/op	       2 allocs/op
   629  func BenchmarkFilter(b *testing.B) {
   630  
   631  	orig := MakeSliceSample()
   632  
   633  	b.ResetTimer()
   634  	b.Run("loncha.Filter ", func(b *testing.B) {
   635  		for i := 0; i < b.N; i++ {
   636  			b.StopTimer()
   637  			objs := make([]Element, len(orig))
   638  			copy(objs, orig)
   639  			b.StartTimer()
   640  			OldFilter(&objs, func(i int) bool {
   641  				return objs[i].ID == 555
   642  			})
   643  		}
   644  	})
   645  
   646  	b.ResetTimer()
   647  	b.Run("loncha.oFilter2", func(b *testing.B) {
   648  		for i := 0; i < b.N; i++ {
   649  			b.StopTimer()
   650  			objs := make([]Element, len(orig))
   651  			copy(objs, orig)
   652  			b.StartTimer()
   653  			Filter(objs,
   654  				nil,
   655  				Cond[FilterOpt[Element]](func(i int) bool {
   656  					return objs[i].ID == 555
   657  				}))
   658  		}
   659  	})
   660  
   661  	b.ResetTimer()
   662  	b.Run("loncha.Filter2 ", func(b *testing.B) {
   663  		for i := 0; i < b.N; i++ {
   664  			b.StopTimer()
   665  			objs := make([]Element, len(orig))
   666  			copy(objs, orig)
   667  			b.StartTimer()
   668  			objs, _ = Filter(objs, nil,
   669  				Cond2[FilterOpt[Element]](func(obj *Element) bool {
   670  					return obj.ID == 555
   671  				}))
   672  		}
   673  	})
   674  	b.ResetTimer()
   675  	b.Run("loncha.Filter2.3 ", func(b *testing.B) {
   676  		for i := 0; i < b.N; i++ {
   677  			b.StopTimer()
   678  			objs := make([]Element, len(orig))
   679  			copy(objs, orig)
   680  			b.StartTimer()
   681  			objs, _ = Filter(objs, nil,
   682  				FilterVersion[FilterOpt[Element]](3),
   683  				Cond2[FilterOpt[Element]](func(obj *Element) bool {
   684  					return obj.ID == 555
   685  				}))
   686  		}
   687  	})
   688  	b.ResetTimer()
   689  	b.Run("loncha.Filter2.4 ", func(b *testing.B) {
   690  		for i := 0; i < b.N; i++ {
   691  			b.StopTimer()
   692  			objs := make([]Element, len(orig))
   693  			copy(objs, orig)
   694  			b.StartTimer()
   695  			objs, _ = Filter(objs, nil,
   696  				FilterVersion[FilterOpt[Element]](4),
   697  				Cond2[FilterOpt[Element]](func(obj *Element) bool {
   698  					return obj.ID == 555
   699  				}))
   700  		}
   701  	})
   702  
   703  	b.ResetTimer()
   704  	b.Run("loncha.Filterable ", func(b *testing.B) {
   705  		for i := 0; i < b.N; i++ {
   706  			b.StopTimer()
   707  			objs := make([]Element, len(orig))
   708  			copy(objs, orig)
   709  			b.StartTimer()
   710  			objs = Filterable(func(obj *Element) bool {
   711  				return obj.ID == 555
   712  			})(objs)
   713  
   714  		}
   715  	})
   716  
   717  	pObjs := MakePtrSliceSample()
   718  	b.ResetTimer()
   719  	b.Run("loncha.Filter pointer", func(b *testing.B) {
   720  		for i := 0; i < b.N; i++ {
   721  			b.StopTimer()
   722  			objs := make([]*Element, 0, len(pObjs))
   723  			copy(objs, pObjs)
   724  			b.StartTimer()
   725  			OldFilter(&objs, func(i int) bool {
   726  				return objs[i].ID == 555
   727  			})
   728  		}
   729  	})
   730  
   731  	b.ResetTimer()
   732  	b.Run("hand Filter pointer", func(b *testing.B) {
   733  		for i := 0; i < b.N; i++ {
   734  			b.StopTimer()
   735  			objs := make([]*Element, len(orig))
   736  			copy(objs, pObjs)
   737  			b.StartTimer()
   738  			result := make([]*Element, 0, len(orig))
   739  			for idx, _ := range objs {
   740  				if objs[idx].ID == 555 {
   741  					result = append(result, objs[idx])
   742  				}
   743  			}
   744  		}
   745  	})
   746  
   747  	b.ResetTimer()
   748  	b.Run("go-funk.Filter", func(b *testing.B) {
   749  		for i := 0; i < b.N; i++ {
   750  			b.StopTimer()
   751  			objs := make([]Element, len(orig))
   752  			copy(objs, orig)
   753  			b.StartTimer()
   754  			funk.Filter(objs, func(e Element) bool {
   755  				return e.ID == 555
   756  			})
   757  		}
   758  	})
   759  
   760  	b.ResetTimer()
   761  	b.Run("go-funk.Filter pointer", func(b *testing.B) {
   762  		for i := 0; i < b.N; i++ {
   763  			b.StopTimer()
   764  			objs := make([]*Element, 0, len(pObjs))
   765  			copy(objs, pObjs)
   766  			b.StartTimer()
   767  			funk.Filter(objs, func(e *Element) bool {
   768  				return e.ID == 555
   769  			})
   770  		}
   771  	})
   772  }
   773  
   774  // BenchmarkUniq/loncha.Uniq-16         	    			1000	    997543 ns/op	  548480 B/op	   16324 allocs/op
   775  // BenchmarkUniq/loncha.UniqWithSort-16 	    			1000	   2237924 ns/op	     256 B/op	       7 allocs/op
   776  // BenchmarkUniq/loncha.UniqWithSort(sort)-16         	    1000	    260283 ns/op	     144 B/op	       4 allocs/op
   777  // BenchmarkUniq/hand_Uniq-16                          	    1000	    427765 ns/op	  442642 B/op	       8 allocs/op
   778  // BenchmarkUniq/hand_Uniq_iface-16                    	    1000	    808895 ns/op	  632225 B/op	    6322 allocs/op
   779  // BenchmarkUniq/go-funk.Uniq-16                       	    1000	   1708396 ns/op	  655968 B/op	   10004 allocs/op
   780  func BenchmarkUniq(b *testing.B) {
   781  
   782  	orig := MakeSliceSample()
   783  
   784  	b.ResetTimer()
   785  	b.Run("loncha.UniqWithSort(before sort)", func(b *testing.B) {
   786  		for i := 0; i < b.N; i++ {
   787  			b.StopTimer()
   788  			objs := make([]Element, len(orig))
   789  			copy(objs, orig)
   790  			sort.Slice(objs, func(i, j int) bool {
   791  				return objs[i].ID < objs[j].ID
   792  			})
   793  			b.StartTimer()
   794  			UniqWithSort(&objs, func(i, j int) bool {
   795  				return objs[i].ID < objs[j].ID
   796  			})
   797  		}
   798  	})
   799  
   800  	b.ResetTimer()
   801  	b.Run("loncha.UniqWithSort", func(b *testing.B) {
   802  		for i := 0; i < b.N; i++ {
   803  			b.StopTimer()
   804  			objs := make([]Element, len(orig))
   805  			copy(objs, orig)
   806  			b.StartTimer()
   807  			UniqWithSort(&objs, func(i, j int) bool {
   808  				return objs[i].ID < objs[j].ID
   809  			})
   810  		}
   811  	})
   812  
   813  	b.ResetTimer()
   814  	b.Run("loncha.Uniq", func(b *testing.B) {
   815  		for i := 0; i < b.N; i++ {
   816  			b.StopTimer()
   817  			objs := make([]Element, len(orig))
   818  			copy(objs, orig)
   819  			b.StartTimer()
   820  			Uniq(&objs, func(i int) interface{} {
   821  				return objs[i].ID
   822  			})
   823  		}
   824  	})
   825  
   826  	b.Run("loncha.Uniq2", func(b *testing.B) {
   827  		for i := 0; i < b.N; i++ {
   828  			b.StopTimer()
   829  			objs := make([]Element, len(orig))
   830  			copy(objs, orig)
   831  			b.StartTimer()
   832  			Uniq2(&objs, func(i, j int) bool {
   833  				return objs[i].ID == objs[j].ID
   834  			})
   835  		}
   836  	})
   837  
   838  	b.ResetTimer()
   839  	b.Run("hand Uniq", func(b *testing.B) {
   840  		for i := 0; i < b.N; i++ {
   841  			b.StopTimer()
   842  			objs := make([]Element, len(orig))
   843  			copy(objs, orig)
   844  			b.StartTimer()
   845  			exists := make(map[int]bool, len(objs))
   846  			result := make([]Element, 0, len(orig))
   847  			for idx, _ := range objs {
   848  				if !exists[objs[idx].ID] {
   849  					exists[objs[idx].ID] = true
   850  					result = append(result, orig[idx])
   851  				}
   852  			}
   853  		}
   854  	})
   855  
   856  	b.ResetTimer()
   857  	b.Run("hand Uniq iface", func(b *testing.B) {
   858  		for i := 0; i < b.N; i++ {
   859  			b.StopTimer()
   860  			objs := make([]Element, len(orig))
   861  			copy(objs, orig)
   862  			b.StartTimer()
   863  			exists := make(map[interface{}]bool, len(objs))
   864  			result := make([]Element, 0, len(orig))
   865  			for idx, _ := range objs {
   866  				if !exists[objs[idx].ID] {
   867  					exists[objs[idx].ID] = true
   868  					result = append(result, orig[idx])
   869  				}
   870  			}
   871  		}
   872  	})
   873  
   874  	b.ResetTimer()
   875  	b.Run("go-funk.Uniq", func(b *testing.B) {
   876  		for i := 0; i < b.N; i++ {
   877  			b.StopTimer()
   878  			objs := make([]Element, len(orig))
   879  			copy(objs, orig)
   880  			b.StartTimer()
   881  			funk.Uniq(objs)
   882  		}
   883  	})
   884  }
   885  
   886  func BenchmarkSelect(b *testing.B) {
   887  	orig := MakeSliceSample()
   888  
   889  	b.ResetTimer()
   890  	b.Run("loncha.Select", func(b *testing.B) {
   891  		for i := 0; i < b.N; i++ {
   892  			b.StopTimer()
   893  			objs := make([]Element, len(orig))
   894  			copy(objs, orig)
   895  			b.StartTimer()
   896  			Select(&objs, func(i int) bool {
   897  				return objs[i].ID == 555
   898  			})
   899  		}
   900  	})
   901  
   902  	b.ResetTimer()
   903  	b.Run("loncha.FilterAndCopy", func(b *testing.B) {
   904  		for i := 0; i < b.N; i++ {
   905  			b.StopTimer()
   906  			objs := make([]Element, len(orig))
   907  			copy(objs, orig)
   908  			b.StartTimer()
   909  			OldFilter(&objs, func(i int) bool {
   910  				return objs[i].ID == 555
   911  			})
   912  			newObjs := make([]Element, len(orig))
   913  			copy(newObjs, objs)
   914  		}
   915  	})
   916  
   917  	b.ResetTimer()
   918  	b.Run("hand Select", func(b *testing.B) {
   919  		for i := 0; i < b.N; i++ {
   920  			b.StopTimer()
   921  			objs := make([]Element, len(orig))
   922  			copy(objs, orig)
   923  			b.StartTimer()
   924  			result := make([]Element, len(orig))
   925  			for idx, _ := range objs {
   926  				if objs[idx].ID == 555 {
   927  					result = append(result, objs[idx])
   928  				}
   929  			}
   930  		}
   931  	})
   932  
   933  }
   934  
   935  type TestInterface interface {
   936  	Inc() int
   937  	Name() string
   938  }
   939  
   940  type TestObject struct {
   941  	Cnt  int
   942  	name string
   943  }
   944  
   945  func (o TestObject) Inc() int {
   946  	o.Cnt++
   947  	return o.Cnt
   948  }
   949  
   950  func (o TestObject) Name() string {
   951  	return o.name
   952  }
   953  
   954  func BenchmarkCall(b *testing.B) {
   955  
   956  	b.ResetTimer()
   957  	b.Run("struct call", func(b *testing.B) {
   958  		for i := 0; i < b.N; i++ {
   959  			b.StopTimer()
   960  			object := TestObject{Cnt: 0, name: "Test"}
   961  			b.StartTimer()
   962  			for j := 0; j < 100000; j++ {
   963  				object.Inc()
   964  			}
   965  		}
   966  	})
   967  
   968  	b.ResetTimer()
   969  	b.Run("interface call", func(b *testing.B) {
   970  		for i := 0; i < b.N; i++ {
   971  			b.StopTimer()
   972  			object := TestInterface(TestObject{Cnt: 0, name: "Test"})
   973  			b.StartTimer()
   974  			for j := 0; j < 100000; j++ {
   975  				object.Inc()
   976  			}
   977  		}
   978  	})
   979  }
   980  
   981  func (list PtrElements) Len() int           { return len(list) }
   982  func (list PtrElements) Swap(i, j int)      { list[i], list[j] = list[j], list[i] }
   983  func (list PtrElements) Less(i, j int) bool { return list[i].ID < list[j].ID }
   984  
   985  // BenchmarkSortPtr/sort.Sort-16         	    1000	   1712284 ns/op	      32 B/op	       1 allocs/op
   986  // BenchmarkSortPtr/sort.Slice-16        	    2000	   1170132 ns/op	      64 B/op	       2 allocs/op
   987  
   988  func BenchmarkSortPtr(b *testing.B) {
   989  	orig := MakePtrSliceSample()
   990  
   991  	b.ResetTimer()
   992  	b.Run("sort.Sort", func(b *testing.B) {
   993  		for i := 0; i < b.N; i++ {
   994  			b.StopTimer()
   995  			data := make(PtrElements, len(orig))
   996  			copy(data, orig)
   997  			b.StartTimer()
   998  			sort.Sort(data)
   999  		}
  1000  	})
  1001  
  1002  	b.ResetTimer()
  1003  	b.Run("sort.Slice", func(b *testing.B) {
  1004  		for i := 0; i < b.N; i++ {
  1005  			b.StopTimer()
  1006  			data := make([]*Element, len(orig))
  1007  			copy(data, orig)
  1008  			b.StartTimer()
  1009  			sort.Slice(data, func(i, j int) bool { return data[i].ID < data[j].ID })
  1010  		}
  1011  	})
  1012  }
  1013  
  1014  func (list Elements) Len() int           { return len(list) }
  1015  func (list Elements) Swap(i, j int)      { list[i], list[j] = list[j], list[i] }
  1016  func (list Elements) Less(i, j int) bool { return list[i].ID < list[j].ID }
  1017  
  1018  // BenchmarkSort/sort.Sort-16         	    1000	   1648947 ns/op	      34 B/op	       1 allocs/op
  1019  // BenchmarkSort/sort.Slice-16        	    1000	   1973036 ns/op	     112 B/op	       3 allocs/op
  1020  
  1021  func BenchmarkSort(b *testing.B) {
  1022  	orig := MakeSliceSample()
  1023  
  1024  	b.ResetTimer()
  1025  	b.Run("sort.Sort", func(b *testing.B) {
  1026  		for i := 0; i < b.N; i++ {
  1027  			b.StopTimer()
  1028  			data := make(Elements, len(orig))
  1029  			copy(data, orig)
  1030  			b.StartTimer()
  1031  			sort.Sort(data)
  1032  		}
  1033  	})
  1034  
  1035  	b.ResetTimer()
  1036  	b.Run("sort.Slice", func(b *testing.B) {
  1037  		for i := 0; i < b.N; i++ {
  1038  			b.StopTimer()
  1039  			data := make([]Element, len(orig))
  1040  			copy(data, orig)
  1041  			b.StartTimer()
  1042  			sort.Slice(data, func(i, j int) bool { return data[i].ID < data[j].ID })
  1043  		}
  1044  	})
  1045  }