github.com/webx-top/com@v1.2.12/slice.go (about) 1 // Copyright 2013 com authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package com 16 17 import ( 18 "errors" 19 "math/rand" 20 "reflect" 21 "sort" 22 "strings" 23 "time" 24 ) 25 26 func WithPrefix(strs []string, prefix string) []string { 27 for k, v := range strs { 28 strs[k] = prefix + v 29 } 30 return strs 31 } 32 33 func WithSuffix(strs []string, suffix string) []string { 34 for k, v := range strs { 35 strs[k] = v + suffix 36 } 37 return strs 38 } 39 40 // AppendStr appends string to slice with no duplicates. 41 func AppendStr(strs []string, str string) []string { 42 for _, s := range strs { 43 if s == str { 44 return strs 45 } 46 } 47 return append(strs, str) 48 } 49 50 // CompareSliceStr compares two 'string' type slices. 51 // It returns true if elements and order are both the same. 52 func CompareSliceStr(s1, s2 []string) bool { 53 if len(s1) != len(s2) { 54 return false 55 } 56 57 for i := range s1 { 58 if s1[i] != s2[i] { 59 return false 60 } 61 } 62 63 return true 64 } 65 66 // CompareSliceStrU compares two 'string' type slices. 67 // It returns true if elements are the same, and ignores the order. 68 func CompareSliceStrU(s1, s2 []string) bool { 69 if len(s1) != len(s2) { 70 return false 71 } 72 73 for i := range s1 { 74 for j := len(s2) - 1; j >= 0; j-- { 75 if s1[i] == s2[j] { 76 s2 = append(s2[:j], s2[j+1:]...) 77 break 78 } 79 } 80 } 81 if len(s2) > 0 { 82 return false 83 } 84 return true 85 } 86 87 // IsSliceContainsStr returns true if the string exists in given slice. 88 func IsSliceContainsStr(sl []string, str string) bool { 89 str = strings.ToLower(str) 90 for _, s := range sl { 91 if strings.ToLower(s) == str { 92 return true 93 } 94 } 95 return false 96 } 97 98 // IsSliceContainsInt64 returns true if the int64 exists in given slice. 99 func IsSliceContainsInt64(sl []int64, i int64) bool { 100 for _, s := range sl { 101 if s == i { 102 return true 103 } 104 } 105 return false 106 } 107 108 // ============================== 109 type reducetype func(interface{}) interface{} 110 type filtertype func(interface{}) bool 111 112 func InSlice(v string, sl []string) bool { 113 for _, vv := range sl { 114 if vv == v { 115 return true 116 } 117 } 118 return false 119 } 120 121 func InSet(v string, sl string, seperator ...string) bool { 122 var sep string 123 if len(seperator) > 0 { 124 sep = seperator[0] 125 } 126 if len(sep) == 0 { 127 sep = `,` 128 } 129 for _, vv := range strings.Split(sl, sep) { 130 if vv == v { 131 return true 132 } 133 } 134 return false 135 } 136 137 func InSliceIface(v interface{}, sl []interface{}) bool { 138 for _, vv := range sl { 139 if vv == v { 140 return true 141 } 142 } 143 return false 144 } 145 146 func InStringSlice(v string, sl []string) bool { 147 return InSlice(v, sl) 148 } 149 150 func InInterfaceSlice(v interface{}, sl []interface{}) bool { 151 return InSliceIface(v, sl) 152 } 153 154 func InIntSlice(v int, sl []int) bool { 155 for _, vv := range sl { 156 if vv == v { 157 return true 158 } 159 } 160 return false 161 } 162 163 func InInt32Slice(v int32, sl []int32) bool { 164 for _, vv := range sl { 165 if vv == v { 166 return true 167 } 168 } 169 return false 170 } 171 172 func InInt16Slice(v int16, sl []int16) bool { 173 for _, vv := range sl { 174 if vv == v { 175 return true 176 } 177 } 178 return false 179 } 180 181 func InInt64Slice(v int64, sl []int64) bool { 182 for _, vv := range sl { 183 if vv == v { 184 return true 185 } 186 } 187 return false 188 } 189 190 func InUintSlice(v uint, sl []uint) bool { 191 for _, vv := range sl { 192 if vv == v { 193 return true 194 } 195 } 196 return false 197 } 198 199 func InUint32Slice(v uint32, sl []uint32) bool { 200 for _, vv := range sl { 201 if vv == v { 202 return true 203 } 204 } 205 return false 206 } 207 208 func InUint16Slice(v uint16, sl []uint16) bool { 209 for _, vv := range sl { 210 if vv == v { 211 return true 212 } 213 } 214 return false 215 } 216 217 func InUint64Slice(v uint64, sl []uint64) bool { 218 for _, vv := range sl { 219 if vv == v { 220 return true 221 } 222 } 223 return false 224 } 225 226 func SliceRandList(min, max int) []int { 227 if max < min { 228 min, max = max, min 229 } 230 length := max - min + 1 231 t0 := time.Now() 232 rand.Seed(int64(t0.Nanosecond())) 233 list := rand.Perm(length) 234 for index := range list { 235 list[index] += min 236 } 237 return list 238 } 239 240 func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) { 241 c = append(slice1, slice2...) 242 return 243 } 244 245 func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) { 246 for _, v := range slice { 247 dslice = append(dslice, a(v)) 248 } 249 return 250 } 251 252 func SliceRand(a []interface{}) (b interface{}) { 253 randnum := rand.Intn(len(a)) 254 b = a[randnum] 255 return 256 } 257 258 func SliceSum(intslice []int64) (sum int64) { 259 for _, v := range intslice { 260 sum += v 261 } 262 return 263 } 264 265 func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) { 266 for _, v := range slice { 267 if a(v) { 268 ftslice = append(ftslice, v) 269 } 270 } 271 return 272 } 273 274 func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) { 275 for _, v := range slice1 { 276 if !InSliceIface(v, slice2) { 277 diffslice = append(diffslice, v) 278 } 279 } 280 return 281 } 282 283 func StringSliceDiff(slice1, slice2 []string) (diffslice []string) { 284 for _, v := range slice1 { 285 if !InSlice(v, slice2) { 286 diffslice = append(diffslice, v) 287 } 288 } 289 return 290 } 291 292 func SliceExtract(parts []string, recv ...*string) { 293 recvEndIndex := len(recv) - 1 294 if recvEndIndex < 0 { 295 return 296 } 297 for index, value := range parts { 298 if index > recvEndIndex { 299 break 300 } 301 *recv[index] = value 302 } 303 } 304 305 func UintSliceDiff(slice1, slice2 []uint) (diffslice []uint) { 306 for _, v := range slice1 { 307 if !InUintSlice(v, slice2) { 308 diffslice = append(diffslice, v) 309 } 310 } 311 return 312 } 313 314 func IntSliceDiff(slice1, slice2 []int) (diffslice []int) { 315 for _, v := range slice1 { 316 if !InIntSlice(v, slice2) { 317 diffslice = append(diffslice, v) 318 } 319 } 320 return 321 } 322 323 func Uint64SliceDiff(slice1, slice2 []uint64) (diffslice []uint64) { 324 for _, v := range slice1 { 325 if !InUint64Slice(v, slice2) { 326 diffslice = append(diffslice, v) 327 } 328 } 329 return 330 } 331 332 func Int64SliceDiff(slice1, slice2 []int64) (diffslice []int64) { 333 for _, v := range slice1 { 334 if !InInt64Slice(v, slice2) { 335 diffslice = append(diffslice, v) 336 } 337 } 338 return 339 } 340 341 func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) { 342 for _, v := range slice1 { 343 if !InSliceIface(v, slice2) { 344 diffslice = append(diffslice, v) 345 } 346 } 347 return 348 } 349 350 func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) { 351 if size >= len(slice) { 352 chunkslice = append(chunkslice, slice) 353 return 354 } 355 end := size 356 for i := 0; i <= (len(slice) - size); i += size { 357 chunkslice = append(chunkslice, slice[i:end]) 358 end += size 359 } 360 return 361 } 362 363 func SliceRange(start, end, step int64) (intslice []int64) { 364 for i := start; i <= end; i += step { 365 intslice = append(intslice, i) 366 } 367 return 368 } 369 370 func SlicePad(slice []interface{}, size int, val interface{}) []interface{} { 371 if size <= len(slice) { 372 return slice 373 } 374 for i := 0; i < (size - len(slice)); i++ { 375 slice = append(slice, val) 376 } 377 return slice 378 } 379 380 func SliceUnique(slice []interface{}) (uniqueslice []interface{}) { 381 for _, v := range slice { 382 if !InSliceIface(v, uniqueslice) { 383 uniqueslice = append(uniqueslice, v) 384 } 385 } 386 return 387 } 388 389 func SliceShuffle(slice []interface{}) []interface{} { 390 size := len(slice) 391 for i := 0; i < size; i++ { 392 a := rand.Intn(size) 393 b := rand.Intn(size) 394 if a == b { 395 continue 396 } 397 slice[a], slice[b] = slice[b], slice[a] 398 } 399 return slice 400 } 401 402 var ErrNotSliceType = errors.New("expects a slice type") 403 404 // Shuffle 打乱数组 405 func Shuffle(arr interface{}) error { 406 contentType := reflect.TypeOf(arr) 407 if contentType.Kind() != reflect.Slice { 408 return ErrNotSliceType 409 } 410 contentValue := reflect.ValueOf(arr) 411 source := rand.NewSource(time.Now().UnixNano()) 412 random := rand.New(source) 413 len := contentValue.Len() 414 for i := len - 1; i > 0; i-- { 415 j := random.Intn(i + 1) 416 x, y := contentValue.Index(i).Interface(), contentValue.Index(j).Interface() 417 contentValue.Index(i).Set(reflect.ValueOf(y)) 418 contentValue.Index(j).Set(reflect.ValueOf(x)) 419 } 420 return nil 421 } 422 423 func SliceInsert(slice, insertion []interface{}, index int) []interface{} { 424 result := make([]interface{}, len(slice)+len(insertion)) 425 at := copy(result, slice[:index]) 426 at += copy(result[at:], insertion) 427 copy(result[at:], slice[index:]) 428 return result 429 } 430 431 // SliceRemove SliceRomove(a,4,5) //a[4] 432 func SliceRemove(slice []interface{}, start int, args ...int) []interface{} { 433 var end int 434 if len(args) == 0 { 435 end = start + 1 436 } else { 437 end = args[0] 438 } 439 if end > len(slice)-1 { 440 return slice[:start] 441 } 442 return append(slice[:start], slice[end:]...) 443 } 444 445 func SliceGet(slice []interface{}, index int, defautls ...interface{}) interface{} { 446 if index >= 0 && index < len(slice) { 447 return slice[index] 448 } 449 if len(defautls) > 0 { 450 if fn, ok := defautls[0].(func() interface{}); ok { 451 return fn() 452 } 453 return defautls[0] 454 } 455 return nil 456 } 457 458 func StrSliceGet(slice []string, index int, defautls ...string) string { 459 if index >= 0 && index < len(slice) { 460 return slice[index] 461 } 462 if len(defautls) > 0 { 463 return defautls[0] 464 } 465 return `` 466 } 467 468 func IntSliceGet(slice []int, index int, defautls ...int) int { 469 if index >= 0 && index < len(slice) { 470 return slice[index] 471 } 472 if len(defautls) > 0 { 473 return defautls[0] 474 } 475 return 0 476 } 477 478 func UintSliceGet(slice []uint, index int, defautls ...uint) uint { 479 if index >= 0 && index < len(slice) { 480 return slice[index] 481 } 482 if len(defautls) > 0 { 483 return defautls[0] 484 } 485 return 0 486 } 487 488 func Int32SliceGet(slice []int32, index int, defautls ...int32) int32 { 489 if index >= 0 && index < len(slice) { 490 return slice[index] 491 } 492 if len(defautls) > 0 { 493 return defautls[0] 494 } 495 return 0 496 } 497 498 func Uint32SliceGet(slice []uint32, index int, defautls ...uint32) uint32 { 499 if index >= 0 && index < len(slice) { 500 return slice[index] 501 } 502 if len(defautls) > 0 { 503 return defautls[0] 504 } 505 return 0 506 } 507 508 func Int64SliceGet(slice []int64, index int, defautls ...int64) int64 { 509 if index >= 0 && index < len(slice) { 510 return slice[index] 511 } 512 if len(defautls) > 0 { 513 return defautls[0] 514 } 515 return 0 516 } 517 518 func Uint64SliceGet(slice []uint64, index int, defautls ...uint64) uint64 { 519 if index >= 0 && index < len(slice) { 520 return slice[index] 521 } 522 if len(defautls) > 0 { 523 return defautls[0] 524 } 525 return 0 526 } 527 528 // SliceRemoveCallback : 根据条件删除 529 // a=[]int{1,2,3,4,5,6} 530 // 531 // SliceRemoveCallback(len(a), func(i int) func(bool)error{ 532 // if a[i]!=4 { 533 // return nil 534 // } 535 // return func(inside bool)error{ 536 // if inside { 537 // a=append(a[0:i],a[i+1:]...) 538 // }else{ 539 // a=a[0:i] 540 // } 541 // return nil 542 // } 543 // }) 544 func SliceRemoveCallback(length int, callback func(int) func(bool) error) error { 545 for i, j := 0, length-1; i <= j; i++ { 546 if removeFunc := callback(i); removeFunc != nil { 547 var err error 548 if i+1 <= j { 549 err = removeFunc(true) 550 } else { 551 err = removeFunc(false) 552 } 553 if err != nil { 554 return err 555 } 556 i-- 557 j-- 558 } 559 } 560 return nil 561 } 562 563 func SplitKVRows(rows string, seperator ...string) map[string]string { 564 sep := `=` 565 if len(seperator) > 0 && len(seperator[0]) > 0 { 566 sep = seperator[0] 567 } 568 res := map[string]string{} 569 for _, row := range strings.Split(rows, StrLF) { 570 parts := strings.SplitN(row, sep, 2) 571 if len(parts) != 2 { 572 continue 573 } 574 parts[0] = strings.TrimSpace(parts[0]) 575 if len(parts[0]) == 0 { 576 continue 577 } 578 parts[1] = strings.TrimSpace(parts[1]) 579 res[parts[0]] = parts[1] 580 } 581 return res 582 } 583 584 func SplitKVRowsCallback(rows string, callback func(k, v string) error, seperator ...string) (err error) { 585 sep := `=` 586 if len(seperator) > 0 && len(seperator[0]) > 0 { 587 sep = seperator[0] 588 } 589 for _, row := range strings.Split(rows, StrLF) { 590 parts := strings.SplitN(row, sep, 2) 591 if len(parts) != 2 { 592 continue 593 } 594 parts[0] = strings.TrimSpace(parts[0]) 595 if len(parts[0]) == 0 { 596 continue 597 } 598 parts[1] = strings.TrimSpace(parts[1]) 599 err = callback(parts[0], parts[1]) 600 if err != nil { 601 return 602 } 603 } 604 return 605 } 606 607 func JoinKVRows(value interface{}, seperator ...string) string { 608 m, y := value.(map[string]string) 609 if !y { 610 return `` 611 } 612 sep := `=` 613 if len(seperator) > 0 && len(seperator[0]) > 0 { 614 sep = seperator[0] 615 } 616 r := make([]string, 0, len(m)) 617 for k, v := range m { 618 r = append(r, k+sep+v) 619 } 620 sort.Strings(r) 621 return strings.Join(r, "\n") 622 } 623 624 func TrimSpaceForRows(rows string) []string { 625 rowSlice := strings.Split(rows, StrLF) 626 res := make([]string, 0, len(rowSlice)) 627 for _, row := range rowSlice { 628 row = strings.TrimSpace(row) 629 if len(row) == 0 { 630 continue 631 } 632 res = append(res, row) 633 } 634 return res 635 }