github.com/viant/toolbox@v0.34.5/collections.go (about) 1 package toolbox 2 3 import ( 4 "fmt" 5 "github.com/pkg/errors" 6 "reflect" 7 "sort" 8 "strings" 9 ) 10 11 //TrueValueProvider is a function that returns true, it takes one parameters which ignores, 12 //This provider can be used to make map from slice like map[some type]bool 13 var TrueValueProvider = func(ignore interface{}) bool { 14 return true 15 } 16 17 //CopyStringValueProvider is a function that returns passed in string 18 //This provider can be used to make map from slice like map[string]some type 19 var CopyStringValueProvider = func(source string) string { 20 return source 21 } 22 23 //ReverseSlice reverse a slice 24 func ReverseSlice(source interface{}) { 25 if source == nil { 26 return 27 } 28 var j = 0 29 switch slice := source.(type) { 30 case []byte: 31 var sliceLen = len(slice) 32 if sliceLen <= 1 { 33 return 34 } 35 for i := sliceLen - 1; i >= (sliceLen / 2); i-- { 36 item := slice[i] 37 slice[i] = slice[j] 38 slice[j] = item 39 j++ 40 } 41 return 42 case []interface{}: 43 var sliceLen = len(slice) 44 if sliceLen <= 1 { 45 return 46 } 47 for i := sliceLen - 1; i >= (sliceLen / 2); i-- { 48 item := slice[i] 49 slice[i] = slice[j] 50 slice[j] = item 51 j++ 52 } 53 return 54 case []string: 55 var sliceLen = len(slice) 56 if sliceLen <= 1 { 57 return 58 } 59 for i := sliceLen - 1; i >= (sliceLen / 2); i-- { 60 item := slice[i] 61 slice[i] = slice[j] 62 slice[j] = item 63 j++ 64 } 65 return 66 } 67 sliceValue := reflect.ValueOf(source) 68 if sliceValue.IsNil() || !sliceValue.IsValid() { 69 return 70 } 71 if sliceValue.Kind() == reflect.Ptr { 72 sliceValue = sliceValue.Elem() 73 } 74 var sliceLen = sliceValue.Len() 75 if sliceLen <= 1 { 76 return 77 } 78 79 for i := sliceLen - 1; i >= (sliceLen / 2); i-- { 80 indexItem := sliceValue.Index(i) 81 indexItemValue := indexItem.Elem() 82 if indexItem.Kind() == reflect.Ptr { 83 sliceValue.Index(i).Set(sliceValue.Index(j).Elem().Addr()) 84 sliceValue.Index(j).Set(indexItemValue.Addr()) 85 } else { 86 sliceValue.Index(i).Set(sliceValue.Index(j).Elem()) 87 sliceValue.Index(j).Set(indexItemValue) 88 } 89 j++ 90 } 91 } 92 93 //ProcessSlice iterates over any slice, it calls handler with each element unless handler returns false, 94 func ProcessSlice(slice interface{}, handler func(item interface{}) bool) { 95 //The common cases with reflection for speed 96 if aSlice, ok := slice.([]interface{}); ok { 97 for _, item := range aSlice { 98 if !handler(item) { 99 break 100 } 101 102 } 103 return 104 } 105 if aSlice, ok := slice.([]map[string]interface{}); ok { 106 for _, item := range aSlice { 107 if !handler(item) { 108 break 109 } 110 111 } 112 return 113 } 114 //The common cases with reflection for speed 115 if aSlice, ok := slice.([]string); ok { 116 for _, item := range aSlice { 117 if !handler(item) { 118 break 119 } 120 } 121 return 122 } 123 124 //The common cases with reflection for speed 125 if aSlice, ok := slice.([]int); ok { 126 for _, item := range aSlice { 127 if !handler(item) { 128 break 129 } 130 } 131 return 132 } 133 134 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 135 for i := 0; i < sliceValue.Len(); i++ { 136 if !handler(sliceValue.Index(i).Interface()) { 137 break 138 } 139 } 140 } 141 142 //ProcessSliceWithIndex iterates over any slice, it calls handler with every index and item unless handler returns false 143 func ProcessSliceWithIndex(slice interface{}, handler func(index int, item interface{}) bool) { 144 if aSlice, ok := slice.([]interface{}); ok { 145 for i, item := range aSlice { 146 if !handler(i, item) { 147 break 148 } 149 } 150 return 151 } 152 if aSlice, ok := slice.([]string); ok { 153 for i, item := range aSlice { 154 if !handler(i, item) { 155 break 156 } 157 } 158 return 159 } 160 if aSlice, ok := slice.([]int); ok { 161 for i, item := range aSlice { 162 if !handler(i, item) { 163 break 164 } 165 } 166 return 167 } 168 169 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 170 for i := 0; i < sliceValue.Len(); i++ { 171 if !handler(i, sliceValue.Index(i).Interface()) { 172 break 173 } 174 } 175 } 176 177 //AsSlice converts underlying slice or Ranger as []interface{} 178 func AsSlice(sourceSlice interface{}) []interface{} { 179 var result []interface{} 180 ranger, ok := sourceSlice.(Ranger) 181 if ok { 182 result = []interface{}{} 183 _ = ranger.Range(func(item interface{}) (bool, error) { 184 result = append(result, item) 185 return true, nil 186 }) 187 return result 188 } 189 iterator, ok := sourceSlice.(Iterator) 190 if ok { 191 if iterator.HasNext() { 192 var item interface{} 193 if err := iterator.Next(&item); err == nil { 194 result = append(result, item) 195 } 196 } 197 } 198 result, ok = sourceSlice.([]interface{}) 199 if ok { 200 return result 201 } 202 if resultPointer, ok := sourceSlice.(*[]interface{}); ok { 203 return *resultPointer 204 } 205 result = make([]interface{}, 0) 206 CopySliceElements(sourceSlice, &result) 207 return result 208 } 209 210 //IndexSlice reads passed in slice and applies function that takes a slice item as argument to return a key value. 211 //passed in resulting map needs to match key type return by a key function, and accept slice item type as argument. 212 func IndexSlice(slice, resultingMap, keyFunction interface{}) { 213 214 mapValue := DiscoverValueByKind(resultingMap, reflect.Map) 215 ProcessSlice(slice, func(item interface{}) bool { 216 result := CallFunction(keyFunction, item) 217 mapValue.SetMapIndex(reflect.ValueOf(result[0]), reflect.ValueOf(item)) 218 return true 219 }) 220 } 221 222 //CopySliceElements appends elements from source slice into target 223 //This function comes handy if you want to copy from generic []interface{} slice to more specific slice like []string, if source slice element are of the same time 224 func CopySliceElements(sourceSlice, targetSlicePointer interface{}) { 225 226 if aTargetSlicePointer, ok := targetSlicePointer.(*[]interface{}); ok { 227 ProcessSlice(sourceSlice, func(item interface{}) bool { 228 *(aTargetSlicePointer) = append(*aTargetSlicePointer, item) 229 return true 230 }) 231 return 232 } 233 234 if aTargetSlicePointer, ok := targetSlicePointer.(*[]string); ok { 235 ProcessSlice(sourceSlice, func(item interface{}) bool { 236 *(aTargetSlicePointer) = append(*aTargetSlicePointer, AsString(item)) 237 return true 238 }) 239 return 240 } 241 AssertPointerKind(targetSlicePointer, reflect.Slice, "targetSlicePointer") 242 sliceValue := reflect.ValueOf(targetSlicePointer).Elem() 243 ProcessSlice(sourceSlice, func(item interface{}) bool { 244 sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(item))) 245 return true 246 }) 247 } 248 249 //TransformSlice appends transformed elements from source slice into target, transformer take as argument item of source slice and return value of target slice. 250 func TransformSlice(sourceSlice, targetSlicePointer, transformer interface{}) { 251 AssertPointerKind(targetSlicePointer, reflect.Slice, "targetSlicePointer") 252 sliceValue := reflect.ValueOf(targetSlicePointer).Elem() 253 ProcessSlice(sourceSlice, func(item interface{}) bool { 254 result := CallFunction(transformer, item) 255 sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(result[0]))) 256 return true 257 }) 258 } 259 260 //FilterSliceElements copies elements from sourceSlice to targetSlice if predicate function returns true. Predicate function needs to accept source slice element type and return true. 261 func FilterSliceElements(sourceSlice interface{}, predicate interface{}, targetSlicePointer interface{}) { 262 //The most common case witout reflection 263 if aTargetSlicePointer, ok := targetSlicePointer.(*[]string); ok { 264 aPredicate, ok := predicate.(func(item string) bool) 265 if !ok { 266 panic("Invalid predicate") 267 } 268 ProcessSlice(sourceSlice, func(item interface{}) bool { 269 if aPredicate(AsString(item)) { 270 *(aTargetSlicePointer) = append(*aTargetSlicePointer, AsString(item)) 271 } 272 return true 273 }) 274 return 275 } 276 AssertPointerKind(targetSlicePointer, reflect.Slice, "targetSlicePointer") 277 slicePointerValue := reflect.ValueOf(targetSlicePointer).Elem() 278 ProcessSlice(sourceSlice, func(item interface{}) bool { 279 result := CallFunction(predicate, item) 280 if AsBoolean(result[0]) { 281 slicePointerValue.Set(reflect.Append(slicePointerValue, reflect.ValueOf(item))) 282 } 283 return true 284 }) 285 } 286 287 //HasSliceAnyElements checks if sourceSlice has any of passed in elements. This method iterates through elements till if finds the first match. 288 func HasSliceAnyElements(sourceSlice interface{}, elements ...interface{}) (result bool) { 289 ProcessSlice(sourceSlice, func(item interface{}) bool { 290 for _, element := range elements { 291 if item == element { 292 result = true 293 return false 294 } 295 } 296 return true 297 }) 298 return result 299 } 300 301 //SliceToMap reads passed in slice to to apply the key and value function for each item. Result of these calls is placed in the resulting map. 302 func SliceToMap(sourceSlice, targetMap, keyFunction, valueFunction interface{}) { 303 //optimized case 304 if stringBoolMap, ok := targetMap.(map[string]bool); ok { 305 if stringSlice, ok := sourceSlice.([]string); ok { 306 if valueFunction, ok := keyFunction.(func(string) bool); ok { 307 if keyFunction, ok := keyFunction.(func(string) string); ok { 308 for _, item := range stringSlice { 309 stringBoolMap[keyFunction(item)] = valueFunction(item) 310 } 311 return 312 } 313 } 314 } 315 } 316 317 mapValue := DiscoverValueByKind(targetMap, reflect.Map) 318 ProcessSlice(sourceSlice, func(item interface{}) bool { 319 key := CallFunction(keyFunction, item) 320 value := CallFunction(valueFunction, item) 321 mapValue.SetMapIndex(reflect.ValueOf(key[0]), reflect.ValueOf(value[0])) 322 return true 323 }) 324 } 325 326 //GroupSliceElements reads source slice and transfer all values returned by keyFunction to a slice in target map. 327 func GroupSliceElements(sourceSlice, targetMap, keyFunction interface{}) { 328 mapValue := DiscoverValueByKind(targetMap, reflect.Map) 329 mapValueType := mapValue.Type().Elem() 330 ProcessSlice(sourceSlice, func(item interface{}) bool { 331 result := CallFunction(keyFunction, item) 332 keyValue := reflect.ValueOf(result[0]) 333 sliceForThisKey := mapValue.MapIndex(keyValue) 334 if !sliceForThisKey.IsValid() { 335 sliceForThisKeyPoiner := reflect.New(mapValueType) 336 sliceForThisKey = sliceForThisKeyPoiner.Elem() 337 mapValue.SetMapIndex(keyValue, sliceForThisKey) 338 } 339 mapValue.SetMapIndex(keyValue, reflect.Append(sliceForThisKey, reflect.ValueOf(item))) 340 return true 341 }) 342 } 343 344 //SliceToMultimap reads source slice and transfer all values by valueFunction and returned by keyFunction to a slice in target map. 345 //Key and value function result type need to agree with target map type. 346 func SliceToMultimap(sourceSlice, targetMap, keyFunction, valueFunction interface{}) { 347 mapValue := DiscoverValueByKind(targetMap, reflect.Map) 348 mapValueType := mapValue.Type().Elem() 349 ProcessSlice(sourceSlice, func(item interface{}) bool { 350 keyResult := CallFunction(keyFunction, item) 351 keyValue := reflect.ValueOf(keyResult[0]) 352 353 valueResult := CallFunction(valueFunction, item) 354 value := reflect.ValueOf(valueResult[0]) 355 sliceForThisKey := mapValue.MapIndex(keyValue) 356 if !sliceForThisKey.IsValid() { 357 sliceForThisKeyPoiner := reflect.New(mapValueType) 358 sliceForThisKey = sliceForThisKeyPoiner.Elem() 359 mapValue.SetMapIndex(keyValue, sliceForThisKey) 360 } 361 mapValue.SetMapIndex(keyValue, reflect.Append(sliceForThisKey, value)) 362 return true 363 }) 364 } 365 366 //SetSliceValue sets value at slice index 367 func SetSliceValue(slice interface{}, index int, value interface{}) { 368 if aSlice, ok := slice.([]string); ok { 369 aSlice[index] = AsString(value) 370 return 371 } 372 if aSlice, ok := slice.([]interface{}); ok { 373 aSlice[index] = value 374 return 375 } 376 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 377 sliceValue.Index(index).Set(reflect.ValueOf(value)) 378 } 379 380 //GetSliceValue gets value from passed in index 381 func GetSliceValue(slice interface{}, index int) interface{} { 382 if aSlice, ok := slice.([]string); ok { 383 return aSlice[index] 384 } 385 if aSlice, ok := slice.([]interface{}); ok { 386 return aSlice[index] 387 } 388 sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice) 389 return sliceValue.Index(index).Interface() 390 } 391 392 var errSliceDoesNotHoldKeyValuePairs = errors.New("unable process map, not key value pairs") 393 394 //ProcessMap iterates over any map, it calls handler with every key, value pair unless handler returns false. 395 func ProcessMap(source interface{}, handler func(key, value interface{}) bool) error { 396 switch aSlice := source.(type) { 397 case map[string]string: 398 for key, value := range aSlice { 399 if !handler(key, value) { 400 break 401 } 402 } 403 return nil 404 case map[string]interface{}: 405 for key, value := range aSlice { 406 if !handler(key, value) { 407 break 408 } 409 } 410 return nil 411 case map[string]bool: 412 for key, value := range aSlice { 413 if !handler(key, value) { 414 break 415 } 416 } 417 return nil 418 case map[string]int: 419 for key, value := range aSlice { 420 if !handler(key, value) { 421 break 422 } 423 } 424 return nil 425 case map[interface{}]interface{}: 426 for key, value := range aSlice { 427 if !handler(key, value) { 428 break 429 } 430 } 431 return nil 432 case map[int]interface{}: 433 for key, value := range aSlice { 434 if !handler(key, value) { 435 break 436 } 437 } 438 return nil 439 440 } 441 if IsSlice(source) { 442 var err error 443 var entryMap map[string]interface{} 444 445 ProcessSlice(source, func(item interface{}) bool { 446 entryMap, err = ToMap(item) 447 if err != nil { 448 return false 449 } 450 var key, value interface{} 451 key, value, err = entryMapToKeyValue(entryMap) 452 if err != nil { 453 return false 454 } 455 return handler(key, value) 456 }) 457 if err != nil { 458 return errSliceDoesNotHoldKeyValuePairs 459 } 460 return nil 461 } 462 463 if !IsMap(source) { 464 return errSliceDoesNotHoldKeyValuePairs 465 } 466 mapValue := DiscoverValueByKind(reflect.ValueOf(source), reflect.Map) 467 for _, key := range mapValue.MapKeys() { 468 value := mapValue.MapIndex(key) 469 if !handler(key.Interface(), value.Interface()) { 470 break 471 } 472 } 473 return nil 474 } 475 476 //ToMap converts underlying map/struct/[]KV as map[string]interface{} 477 func ToMap(source interface{}) (map[string]interface{}, error) { 478 if source == nil { 479 return nil, nil 480 } 481 var result map[string]interface{} 482 switch candidate := source.(type) { 483 case map[string]interface{}: 484 return candidate, nil 485 case *map[string]interface{}: 486 return *candidate, nil 487 case map[interface{}]interface{}: 488 result = make(map[string]interface{}) 489 for k, v := range candidate { 490 result[AsString(k)] = v 491 } 492 return result, nil 493 } 494 if IsStruct(source) { 495 var result = make(map[string]interface{}) 496 if err := DefaultConverter.AssignConverted(&result, source); err != nil { 497 return nil, err 498 } 499 500 return result, nil 501 } else if IsSlice(source) { 502 var result = make(map[string]interface{}) 503 if err := DefaultConverter.AssignConverted(&result, source); err != nil { 504 return nil, err 505 } 506 return result, nil 507 } 508 sourceMapValue := reflect.ValueOf(source) 509 mapType := reflect.TypeOf(result) 510 if sourceMapValue.Type().AssignableTo(mapType) { 511 result, ok := sourceMapValue.Convert(mapType).Interface().(map[string]interface{}) 512 if !ok { 513 return nil, fmt.Errorf("unable to convert: %T to %T", source, map[string]interface{}{}) 514 } 515 return result, nil 516 } 517 result = make(map[string]interface{}) 518 CopyMapEntries(source, result) 519 return result, nil 520 } 521 522 //AsMap converts underlying map as map[string]interface{} 523 func AsMap(source interface{}) map[string]interface{} { 524 if result, err := ToMap(source); err == nil { 525 return result 526 } 527 return nil 528 } 529 530 //CopyMapEntries appends map entry from source map to target map 531 func CopyMapEntries(sourceMap, targetMap interface{}) { 532 targetMapValue := reflect.ValueOf(targetMap) 533 if targetMapValue.Kind() == reflect.Ptr { 534 targetMapValue = targetMapValue.Elem() 535 } 536 if target, ok := targetMap.(map[string]interface{}); ok { 537 _ = ProcessMap(sourceMap, func(key, value interface{}) bool { 538 target[AsString(key)] = value 539 return true 540 }) 541 return 542 } 543 _ = ProcessMap(sourceMap, func(key, value interface{}) bool { 544 targetMapValue.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(value)) 545 return true 546 }) 547 } 548 549 //MapKeysToSlice appends all map keys to targetSlice 550 func MapKeysToSlice(sourceMap interface{}, targetSlicePointer interface{}) error { 551 AssertPointerKind(targetSlicePointer, reflect.Slice, "targetSlicePointer") 552 slicePointerValue := reflect.ValueOf(targetSlicePointer).Elem() 553 return ProcessMap(sourceMap, func(key, value interface{}) bool { 554 slicePointerValue.Set(reflect.Append(slicePointerValue, reflect.ValueOf(key))) 555 return true 556 }) 557 } 558 559 //MapKeysToStringSlice creates a string slice from sourceMap keys, keys do not need to be of a string type. 560 func MapKeysToStringSlice(sourceMap interface{}) []string { 561 var keys = make([]string, 0) 562 //common cases 563 switch aMap := sourceMap.(type) { 564 case map[string]interface{}: 565 for k := range aMap { 566 keys = append(keys, k) 567 } 568 return keys 569 case map[string]bool: 570 for k := range aMap { 571 keys = append(keys, k) 572 } 573 return keys 574 case map[string]int: 575 for k := range aMap { 576 keys = append(keys, k) 577 } 578 return keys 579 } 580 _ = ProcessMap(sourceMap, func(key interface{}, value interface{}) bool { 581 keys = append(keys, AsString(key)) 582 return true 583 }) 584 return keys 585 } 586 587 //Process2DSliceInBatches iterates over any 2 dimensional slice, it calls handler with batch. 588 func Process2DSliceInBatches(slice [][]interface{}, size int, handler func(batchedSlice [][]interface{})) { 589 batchCount := (len(slice) / size) + 1 590 fromIndex, toIndex := 0, 0 591 592 for i := 0; i < batchCount; i++ { 593 toIndex = size * (i + 1) 594 isLastBatch := toIndex >= len(slice) 595 if isLastBatch { 596 toIndex = len(slice) 597 } 598 handler(slice[fromIndex:toIndex]) 599 fromIndex = toIndex 600 601 } 602 } 603 604 //SortStrings creates a new copy of passed in slice and sorts it. 605 func SortStrings(source []string) []string { 606 var result = make([]string, 0) 607 result = append(result, source...) 608 sort.Strings(result) 609 return result 610 } 611 612 //JoinAsString joins all items of a slice, with separator, it takes any slice as argument, 613 func JoinAsString(slice interface{}, separator string) string { 614 result := "" 615 ProcessSlice(slice, func(item interface{}) bool { 616 if len(result) > 0 { 617 result = result + separator 618 } 619 result = fmt.Sprintf("%v%v", result, item) 620 return true 621 }) 622 return result 623 } 624 625 //MakeStringMap creates a mapstring]string from string, 626 func MakeStringMap(text string, valueSeparator string, itemSeparator string) map[string]string { 627 var result = make(map[string]string) 628 for _, item := range strings.Split(text, itemSeparator) { 629 if len(item) == 0 { 630 continue 631 } 632 keyValue := strings.SplitN(item, valueSeparator, 2) 633 if len(keyValue) == 2 { 634 result[strings.Trim(keyValue[0], " \t")] = strings.Trim(keyValue[1], " \n\t") 635 } 636 } 637 return result 638 } 639 640 //MakeMap creates a mapstring]interface{} from string, 641 func MakeMap(text string, valueSeparator string, itemSeparator string) map[string]interface{} { 642 var result = make(map[string]interface{}) 643 for _, item := range strings.Split(text, itemSeparator) { 644 if len(item) == 0 { 645 continue 646 } 647 keyValue := strings.SplitN(item, valueSeparator, 2) 648 if len(keyValue) == 2 { 649 result[strings.Trim(keyValue[0], " \t")] = strings.Trim(keyValue[1], " \n\t") 650 } 651 } 652 return result 653 } 654 655 //MakeReverseStringMap creates a mapstring]string from string, the values become key, and key values 656 func MakeReverseStringMap(text string, valueSepartor string, itemSeparator string) map[string]string { 657 var result = make(map[string]string) 658 for _, item := range strings.Split(text, itemSeparator) { 659 if len(item) == 0 { 660 continue 661 } 662 keyValue := strings.SplitN(item, valueSepartor, 2) 663 if len(keyValue) == 2 { 664 result[strings.Trim(keyValue[1], " \t")] = strings.Trim(keyValue[0], " \n\t") 665 } 666 } 667 return result 668 } 669 670 func isNilOrEmpty(v interface{}) bool { 671 if v == nil { 672 return true 673 } 674 switch value := v.(type) { 675 case string: 676 if value == "" { 677 return true 678 } 679 case int: 680 if value == 0 { 681 return true 682 } 683 case map[string]interface{}: 684 if len(value) == 0 { 685 return true 686 } 687 case map[interface{}]interface{}: 688 if len(value) == 0 { 689 return true 690 } 691 692 case []map[string]interface{}: 693 if len(value) == 0 { 694 return true 695 } 696 case []map[interface{}]interface{}: 697 if len(value) == 0 { 698 return true 699 } 700 case []interface{}: 701 if len(value) == 0 { 702 return true 703 } 704 case interface{}: 705 if value == nil { 706 return true 707 } 708 } 709 return AsString(v) == "" 710 } 711 712 713 714 715 //CopyMap copy source map into destination map, copier function can modify key, value, or return false to skip map entry 716 func CopyMap(input, output interface{}, copier func(key, value interface{}) (interface{},interface{}, bool)) (err error) { 717 var mutator func(k, v interface{}) 718 if aMap, ok := output.(map[interface{}]interface{}); ok { 719 mutator = func(k, v interface{}) { 720 aMap[k] = v 721 } 722 } else if aMap, ok := output.(map[string]interface{}); ok { 723 mutator = func(k, v interface{}) { 724 aMap[AsString(k)] = v 725 } 726 } else { 727 return fmt.Errorf("unsupported map type: %v", output) 728 } 729 730 mapProvider := func(source interface{}) func() interface{} { 731 if _, ok := source.(map[interface{}]interface{}); ok { 732 return func() interface{} { 733 return map[interface{}]interface{}{} 734 } 735 } 736 return func() interface{} { 737 return map[string]interface{}{} 738 } 739 } 740 var ok bool 741 err = ProcessMap(input, func(k, v interface{}) bool { 742 k, v, ok = copier(k, v) 743 if ! ok { 744 return true 745 } 746 if v == nil { 747 // 748 } else if IsMap(v) { 749 transformed := mapProvider(v)() 750 err = CopyMap(v, transformed, copier) 751 if err != nil { 752 return false 753 } 754 if isNilOrEmpty(transformed) { 755 return true 756 } 757 v = transformed 758 759 } else if IsSlice(v) { 760 aSlice := AsSlice(v) 761 var transformed = []interface{}{} 762 for _, item := range aSlice { 763 if isNilOrEmpty(item) { 764 continue 765 } 766 if IsMap(item) { 767 transformedItem := mapProvider(item)() 768 769 err = CopyMap(item, transformedItem, copier) 770 if err != nil { 771 return false 772 } 773 if isNilOrEmpty(transformedItem) { 774 return true 775 } 776 transformed = append(transformed, transformedItem) 777 } else { 778 transformed = append(transformed, item) 779 } 780 781 } 782 if len(transformed) == 0 { 783 return true 784 } 785 v = transformed 786 } 787 mutator(k, v) 788 return true 789 }) 790 return err 791 } 792 793 794 //OmitEmptyMapWriter return false for all nil or empty values 795 func OmitEmptyMapWriter(key, value interface{}) (interface{}, interface{}, bool){ 796 if value == nil { 797 return key, value, false 798 } 799 if IsPointer(value) { 800 if reflect.ValueOf(value).IsNil() { 801 return key, value, false 802 } 803 } 804 if IsString(value) { 805 return key, value, AsString(value) != "" 806 } 807 if IsBool(value) { 808 return key, value, AsBoolean(value) 809 } 810 if IsNumber(value) { 811 return key, value, AsFloat(value) != 0.0 812 } 813 return key, value, true 814 } 815 816 817 818 //CopyNonEmptyMapEntries removes empty keys from map result 819 func CopyNonEmptyMapEntries(input, output interface{}) (err error) { 820 return CopyMap(input, output, func(key, value interface{}) (interface{}, interface{}, bool) { 821 if isNilOrEmpty(value) { 822 return key, value, false 823 } 824 return key, value, true 825 }) 826 } 827 828 //CopyNonEmptyMapEntries removes empty keys from map result 829 func ReplaceMapEntries(input, output interface{}, replacement map[string]interface{}, removeEmpty bool) (err error) { 830 return CopyMap(input, output, func(key, value interface{}) (interface{}, interface{}, bool) { 831 k := AsString(key) 832 if v, ok := replacement[k]; ok { 833 return key, v, ok 834 } 835 if removeEmpty && isNilOrEmpty(value) { 836 return nil, nil, false 837 } 838 return key, value, true 839 }) 840 } 841 842 //DeleteEmptyKeys removes empty keys from map result 843 func DeleteEmptyKeys(input interface{}) map[string]interface{} { 844 result := map[string]interface{}{} 845 err := CopyNonEmptyMapEntries(input, result) 846 if err == nil { 847 return result 848 } 849 return AsMap(input) 850 } 851 852 //DeleteEmptyKeys removes empty keys from map result 853 func ReplaceMapKeys(input interface{}, replacement map[string]interface{}, removeEmpty bool) map[string]interface{} { 854 result := map[string]interface{}{} 855 _ = ReplaceMapEntries(input, result, replacement, removeEmpty) 856 return result 857 } 858 859 //Pairs returns map for pairs. 860 func Pairs(params ...interface{}) map[string]interface{} { 861 var result = make(map[string]interface{}) 862 for i := 0; i+1 < len(params); i += 2 { 863 var key = AsString(params[i]) 864 result[key] = params[i+1] 865 } 866 return result 867 } 868 869 // Intersect find elements presents in slice a and b, match is appended to result slice 870 //It accept generic slices, All slices should have items of the same type or interface{} type 871 func Intersect(a, b interface{}, resultPointer interface{}) error { 872 if reflect.ValueOf(resultPointer).Kind() != reflect.Ptr { 873 return fmt.Errorf("resultPointer has to be pointer but had: %T", resultPointer) 874 } 875 var aItems = make(map[interface{}]bool) 876 ProcessSlice(a, func(item interface{}) bool { 877 aItems[item] = true 878 return true 879 }) 880 881 var appendMatch func(item interface{}) error 882 switch aSlicePrt := resultPointer.(type) { 883 case *[]interface{}: 884 appendMatch = func(item interface{}) error { 885 *aSlicePrt = append(*aSlicePrt, item) 886 return nil 887 } 888 case *[]string: 889 appendMatch = func(item interface{}) error { 890 *aSlicePrt = append(*aSlicePrt, AsString(item)) 891 return nil 892 } 893 case *[]int: 894 appendMatch = func(item interface{}) error { 895 intValue, err := ToInt(item) 896 if err != nil { 897 return err 898 } 899 *aSlicePrt = append(*aSlicePrt, intValue) 900 return nil 901 } 902 default: 903 appendMatch = func(item interface{}) error { 904 sliceValue := reflect.ValueOf(resultPointer).Elem() 905 //TODO add check that type of the slice is assignable from item 906 sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(item))) 907 return nil 908 } 909 } 910 var err error 911 ProcessSlice(b, func(item interface{}) bool { 912 if aItems[item] { 913 if err = appendMatch(item); err != nil { 914 return false 915 } 916 } 917 return true 918 }) 919 return err 920 }