Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 173
Good morning! Here's your coding interview problem for today.

This problem was asked by Stripe.

Write a function to flatten a nested dictionary. Namespace the keys with a period.

For example, given the following dictionary:
```
{
    "key": 3,
    "foo": {
        "a": 5,
        "bar": {
            "baz": 8
        }
    }
}
```
it should become:
```
{
    "key": 3,
    "foo.a": 5,
    "foo.bar.baz": 8
}
```

Pull request description:
Day173
Resolves #360.

Patch:
diff --git a/README.md b/README.md
index 7186829..1f804ba 100644
--- a/README.md
+++ b/README.md
@@ -184,3 +184,4 @@ problems from
 * [Day 170](https://github.com/vaskoz/dailycodingproblem-go/issues/353)
 * [Day 171](https://github.com/vaskoz/dailycodingproblem-go/issues/356)
 * [Day 172](https://github.com/vaskoz/dailycodingproblem-go/issues/358)
+* [Day 173](https://github.com/vaskoz/dailycodingproblem-go/issues/360)
diff --git a/day173/problem.go b/day173/problem.go
new file mode 100644
index 0000000..ad92a6b
--- /dev/null
+++ b/day173/problem.go
@@ -0,0 +1,21 @@
+package day173
+
+import "strings"
+
+// FlattenMap takes an arbitrary map and flattens it.
+// It concatenates keys with '.'
+func FlattenMap(m map[string]interface{}) map[string]interface{} {
+	result := make(map[string]interface{})
+	dfsFlattenMap([]string{}, m, result)
+	return result
+}
+
+func dfsFlattenMap(prefix []string, m, result map[string]interface{}) {
+	for k, v := range m {
+		if obj, ok := v.(map[string]interface{}); ok {
+			dfsFlattenMap(append(prefix, k), obj, result)
+		} else {
+			result[strings.Join(append(prefix, k), ".")] = v
+		}
+	}
+}


Test patch:
diff --git a/day173/problem_test.go b/day173/problem_test.go
new file mode 100644
index 0000000..9815a9f
--- /dev/null
+++ b/day173/problem_test.go
@@ -0,0 +1,42 @@
+package day173
+
+import (
+	"reflect"
+	"testing"
+)
+
+var testcases = []struct {
+	nested, flattened map[string]interface{}
+}{
+	{map[string]interface{}{
+		"key": 3,
+		"foo": map[string]interface{}{
+			"a": 5,
+			"bar": map[string]interface{}{
+				"baz": 8,
+			},
+		},
+	},
+		map[string]interface{}{
+			"key":         3,
+			"foo.a":       5,
+			"foo.bar.baz": 8,
+		}},
+}
+
+func TestFlattenMap(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if result := FlattenMap(tc.nested); !reflect.DeepEqual(result, tc.flattened) {
+			t.Errorf("Expected %v got %v", tc.flattened, result)
+		}
+	}
+}
+
+func BenchmarkFlattenMap(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			FlattenMap(tc.nested)
+		}
+	}
+}