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  }