Here is a word-count function in Go

package wc

import (
    "regexp"
    "strings"
)

type Histogram map[string]int

func WordCount(input string) Histogram {
    histogram := make(map[string]int)
    re := regexp.MustCompile("[^a-zA-Z0-9 ]*")
    input = re.ReplaceAllString(input, "")

    for _, word := range strings.Split(input, " ") {
        if word == "" {
            continue
        }
        histogram[strings.ToLower(word)]++
    }

    return histogram
}

This code passes or fails the tests non-deterministically. Sometimes it failed due to not matching the expected map and the actual map. However, the contents of both are exactly the same. I think that there is some problem with map comparison. I don't know how can I fix it. Somebody help me please!

Here is the test-suite code

package wc

import (
    "fmt"
    "testing"
)

var testCases = []struct {
    description string
    input       string
    output      Histogram
}{
    {
        description: "a single word",
        input:       "word",
        output:      Histogram{"word": 1},
    },
    {
        description: "one of each",
        input:       "one of each",
        output:      Histogram{"one": 1, "of": 1, "each": 1},
    },
    {
        description: "multiple occurrences",
        input:       "one fish two fish red fish blue fish",
        output:      Histogram{"one": 1, "fish": 4, "two": 1, "red": 1, "blue": 1},
    },
    {
        description: "ignore punctuation",
        input:       "car : carpet as java : javascript!!&@$%^&",
        output:      Histogram{"car": 1, "carpet": 1, "as": 1, "java": 1, "javascript": 1},
    },
    {
        description: "including numbers",
        input:       "testing, 1, 2 testing",
        output:      Histogram{"testing": 2, "1": 1, "2": 1},
    },
    {
        description: "normalises case",
        input:       "go Go GO",
        output:      Histogram{"go": 3},
    },
}

func TestWordCount(t *testing.T) {
    for _, tt := range testCases {
        expected := fmt.Sprintf("%v", tt.output)
        actual := fmt.Sprintf("%v", WordCount(tt.input))

        if expected != actual {
            t.Fatalf("%s\n\tExpected: %v\n\tGot: %v", tt.description, expected, actual)
        } else {
            t.Logf("PASS: %s - WordCount(%s)", tt.description, tt.input)
        }
    }
}

Below are examples of the failure situation:

1.
Expected: map[two:1 red:1 blue:1 one:1 fish:4]
Got: map[one:1 fish:4 two:1 red:1 blue:1]
2.
Expected: map[one:1 fish:4 two:1 red:1 blue:1]
Got: map[red:1 blue:1 one:1 fish:4 two:1]
3.
Expected: map[java:1 javascript:1 car:1 carpet:1 as:1]
Got: map[javascript:1 car:1 carpet:1 as:1 java:1]
...

Additional information are here: http://exercism.io/submissions/cf94f4732fd97335be2e755f

有帮助吗?

解决方案

You can't compare expected and actual with !=, because it compares the string representation of the maps, so it will work only randomly (if the values are printed in the same order).

What you have to do, is to use the reflect package DeepEqual() method to compare the maps :

import "reflect"
// ...

if !reflect.DeepEqual(tt.output, WordCount(tt.input)) {
// ...

It will first checks if both maps are nil, then if they have the same length, then if they have the same set of (key, value) pairs.

其他提示

You are not comparing two maps, you are comparing the String() output of two maps. However, when a map is printed or range()'d, the content is randomly picked, so you cannot compare it with strings.

You could compare lengths first, then range() one of them and check if the value of every key in the first map is present and equal to the value of the same key in the second map.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top