 132485adb0
			
		
	
	132485adb0
	
	
	
		
			
			Followed the Migration Guide at https://cli.urfave.org/migrate-v1-to-v2/ The major changes not pointed out in the migration guide are: - context.Args() no longer produces a []slice, so context.Args().Slice() in substitued - All cli.Global***** are deprecated (the migration guide is somewhat unclear on this) Signed-off-by: Derek Nola <derek.nola@suse.com> Vendor in urfave cli/v2 Signed-off-by: Derek Nola <derek.nola@suse.com> Fix NewStringSlice calls Signed-off-by: Derek Nola <derek.nola@suse.com>
		
			
				
	
	
		
			87 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package smetrics
 | |
| 
 | |
| import (
 | |
| 	"math"
 | |
| )
 | |
| 
 | |
| // The Jaro distance. The result is 1 for equal strings, and 0 for completely different strings.
 | |
| func Jaro(a, b string) float64 {
 | |
| 	// If both strings are zero-length, they are completely equal,
 | |
| 	// therefore return 1.
 | |
| 	if len(a) == 0 && len(b) == 0 {
 | |
| 		return 1
 | |
| 	}
 | |
| 
 | |
| 	// If one string is zero-length, strings are completely different,
 | |
| 	// therefore return 0.
 | |
| 	if len(a) == 0 || len(b) == 0 {
 | |
| 		return 0
 | |
| 	}
 | |
| 
 | |
| 	// Define the necessary variables for the algorithm.
 | |
| 	la := float64(len(a))
 | |
| 	lb := float64(len(b))
 | |
| 	matchRange := int(math.Max(0, math.Floor(math.Max(la, lb)/2.0)-1))
 | |
| 	matchesA := make([]bool, len(a))
 | |
| 	matchesB := make([]bool, len(b))
 | |
| 	var matches float64 = 0
 | |
| 
 | |
| 	// Step 1: Matches
 | |
| 	// Loop through each character of the first string,
 | |
| 	// looking for a matching character in the second string.
 | |
| 	for i := 0; i < len(a); i++ {
 | |
| 		start := int(math.Max(0, float64(i-matchRange)))
 | |
| 		end := int(math.Min(lb-1, float64(i+matchRange)))
 | |
| 
 | |
| 		for j := start; j <= end; j++ {
 | |
| 			if matchesB[j] {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			if a[i] == b[j] {
 | |
| 				matchesA[i] = true
 | |
| 				matchesB[j] = true
 | |
| 				matches++
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// If there are no matches, strings are completely different,
 | |
| 	// therefore return 0.
 | |
| 	if matches == 0 {
 | |
| 		return 0
 | |
| 	}
 | |
| 
 | |
| 	// Step 2: Transpositions
 | |
| 	// Loop through the matches' arrays, looking for
 | |
| 	// unaligned matches. Count the number of unaligned matches.
 | |
| 	unaligned := 0
 | |
| 	j := 0
 | |
| 	for i := 0; i < len(a); i++ {
 | |
| 		if !matchesA[i] {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		for !matchesB[j] {
 | |
| 			j++
 | |
| 		}
 | |
| 
 | |
| 		if a[i] != b[j] {
 | |
| 			unaligned++
 | |
| 		}
 | |
| 
 | |
| 		j++
 | |
| 	}
 | |
| 
 | |
| 	// The number of unaligned matches divided by two, is the number of _transpositions_.
 | |
| 	transpositions := math.Floor(float64(unaligned / 2))
 | |
| 
 | |
| 	// Jaro distance is the average between these three numbers:
 | |
| 	// 1. matches / length of string A
 | |
| 	// 2. matches / length of string B
 | |
| 	// 3. (matches - transpositions/matches)
 | |
| 	// So, all that divided by three is the final result.
 | |
| 	return ((matches / la) + (matches / lb) + ((matches - transpositions) / matches)) / 3.0
 | |
| }
 |