Case-insensitive Sorting

Anagram
Anagram in Go
// Package anagram contains a solution to the anagram Exercism exercise.
package anagram

import (
	"sort"
	"strings"
)

// Detect determines which words in candidates are anagrams of the subject.
func Detect(subject string, candidates []string) []string {
	anagrams := make([]string, 0)

	subject = strings.ToLower(subject)

	for _, candidate := range candidates {
		c := strings.ToLower(candidate)

		if isAnagram(subject, c) {
			anagrams = append(anagrams, candidate)
		}
	}

	return anagrams
}

// isAnagram determines whether a and b are anagrams of each other.
func isAnagram(a, b string) bool {
	return a != b && sortString(a) == sortString(b)
}

// sortString sorts a string lexicographically in non-decreasing order.
func sortString(s string) string {
	chars := strings.Split(s, "")
	sort.Strings(chars)
	return strings.Join(chars, "")
}

This approach normalizes both strings to lowercase, sorts them, and compares the resulting sorted strings to determine if they are anagrams.

The strings.ToLower function is used to convert the strings into their lowercase form. This normalizes the strings so that the solution is case-insensitive (e.g., foo and OOF normalize to foo and oof). At this point if the two strings normalize to the same string, they cannot be anagrams since a word cannot be an anagram of itself.

The normalized strings are then sorted using the sort package. It doesn't matter if the strings are sorted in non-decreasing or non-increasing order as long as both strings are sorted in the same way. Sorting the strings allows us to determine if the strings are anagrams (e.g., foo and oof sort to foo and foo). In Go, sorting operates on slices, not strings, so the string is first split into a slice using strings.Split, sorted using sort.Strings, and then joined back into a string using strings.Join.

Now that the strings are normalized and sorted, they can be compared directly to determine if they are anagrams. If the strings are the same, they are anagrams. Otherwise, they are not anagrams.

This approach separates the sorting and anagram checking logic into their own functions for readability. That way, the Detect function can focus on iterating over the candidates and building the resulting slice of anagrams.

7th Aug 2024 · Found it useful?