Gowhere – array, hash table, regular expression, and foreach loop

Gowhere? Some steps further—append arrays, hash table, regular expression, and for each loop.

After playing around with HTTP, I got the JSON data from the API. I wanted to analyze the data—to display the total hours spent on each work item.

A typical record has this structure

type WorkItem struct {
    FromDateTime time.Time
    ToDateTime   time.Time
    Detail       string
}

And an actual work item looks like

{
    "FromDateTime" : "2019-11-29 02:05:00 +0000 UTC",
    "ToDateTime": "2019-11-29 03:19:00 +0000 UTC",
    "Detail" : "Work Item 12345: Implement a cool feature"
}

The "Work Item 12345" has many records. The detail field are not the same except they contain the number 12345 as the work item ID. I want to display the sum of time spent for Work Item 12345. So the algorithm is pretty simple

  1. For each record, extract the work item id from the detail field
  2. Calculate the difference in hours between FromDateTime and ToDateTime
  3. Sum the difference with the existing value—if not exist, create a new one with the time spent zero

Note: If I am writing in C#, I can finish the implementation quickly with Linq support.

The expected result of a work item is below

{
    "WorkItemId" : "12345",
    "WorkItemName" : "Work Item 12345: Implement a cool feature",
    "TimeSpent" : time_spent_in_hours
}

Stats structure to hold the analysis result of a work item

// Stats ...
type Stats struct {
    WorkItemId    string
    WorkItemName  string
    TimeSpent float64
}

Let’s write some code and explore

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "regexp"
    "time"
)

func main() {
    // Assuming that I have a list of IDs for a team.
    // The getWorkItemRecords will an array of WorkItem of a member.
    var records = make([]WorkItem, 0)
    for _, id := range team {
        r := getWorkItemRecords(id)
        // Discussion about appending 2 slices: https://stackoverflow.com/questions/16248241/concatenate-two-slices-in-go

        // This is how to append 2 arrays
        records = append(records, r...)
    }

    // A dictionary (hash table) with
    // key: WorkItemID (or name if cannot find the ID) - simply a string
    // value: total time spent
    // More detail about map here: https://blog.golang.org/go-maps-in-action
    statsMap := make(map[string]Stats)

    // Regular expression to extract ID (all numeric characters)
    workItemIdExp := regexp.MustCompile("[\\d]+")

    var id string

    for _, r := range records {
        timeSpent := r.ToDateTime.Sub(r.FromDateTime).Hours()
        if timeSpent < 0 {
            // The record does not have an end time
            continue
        }

        id = workItemIdExp.FindString(r.Detail)

        if id == "" {
            id = r.Detail
        }

        ts, exist := statsMap[id]

        if !exist {
            ts = Stats{id, r.Detail, 0}
        }
        ts.TimeSpent += timeSpent
        statsMap[id] = ts
    }

    var workingHours float64 = 0
    for key, value := range statsMap {
        workingHours += value.TimeSpent
        fmt.Printf("%s (%s) %f\n", key, value.WorkItemName, value.TimeSpent)
    }

    fmt.Printf("Working hours: %f\n", workingHours)
}

What are my further steps from this exercise?

  1. Append 2 arrays (slices) with "…" syntax—append(records, r...)
  2. Hash table (dictionary like) with mapmap[string]int means a dictionary with key is a string and value is an integer
  3. Regular expression with regexp package—regexp.MustCompile("[\\d]+")
  4. For each loop with the rangefor _, r := range records

A happy weekend!

Write a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.