Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get index of element from array / slice or key of value from map in Go?

Tags:

go

I have an enumerated list of strings (which are constant, e.g. a list of countries), that I'd like to be able to get the string when providing the enumerated int value, and vice-versa be able to get the enumerated int value when providing the string. This is in order to translate between the two for database transactions.

var MyData = [...]string {
  "string1", // index 0
  "string2", // index 1
  "string3", // index 2  
}

That's easy for a language like python, where one can just do something like MyData[1] to get "string2" and MyData.index("string2") to get 1.

A few possible solutions would be to

  • write my own function to get the index by iterating over the array / slice
  • sort the array / slice and use a search function to return index (though this doesn't allow for an unsorted sequence, which is what I'd prefer)
  • maintain a map and an array that mirror each other, which is prone to errors.

Speaking of maps, can one access the key of a particular value? Then I could simply have a map like the following, and be able to get the string key when providing the int value.

var MyData = map[string]int {
  "string1": 0,
  "string2": 1,
  "string3": 2,
}

UPDATE: Before I accept my answer, I want to explain the problem more thoroughly, which I know must be fairly common. I basically have a set of strings that are constant (such as a list of countries) each with an associated integer value. In my database I simply store the integer to conserve space, since there are millions of entries. But when I display an entry from the database I need to display the string value for it to be readable to a user. A simple array will do for that. However, I also need to add entries to the database (such as a new person and their country of residence) and in this scenario need to translate from the country string which is entered in a form to that integer value. Again, this is just an example use case, but the goal remains the same. I need a table that can translate in both directions between a string value and an enumerated int value. The most obvious thing to do is to maintain an array (for the int to string translation) and a map (for the string to int translation). I'd prefer not to manually maintain both variables, since this is prone to errors. So my solution below is to maintain just a single array, and have the constructor method automatically build the map at runtime when the program is first run. This has the advantage of not needing to iterate over the entire array when I fetch the integer value based on the string (which was the other proposed solution).

like image 866
onlinespending Avatar asked Jan 08 '23 19:01

onlinespending


2 Answers

In both cases you should just use the built in range function.

for k, v := range MyData {
}


for i, v := range ThisArray {
}


for i, _ := range ThisArrayIndexOnly {
    value := ThisArrayIndexOnly[i]
}

You can build helper functions or whatever you like on top of this but range is fundamentally the mechanism available for accessing that data. If you want an "indexof" function it would be

for i, v := range ArrayPassedIntoFunction {
     if v == ValuePassedIntoFunction {
          return i
     }
}
return -1

To get the value, you of course would just do MyArray[i] including a bounds check or whatever. Note the pseudo code above is written in a style that indicates it's an array but virtually the same code will work for a map, I would just typically use the var name k instead of i.

like image 193
evanmcdonnal Avatar answered Jan 13 '23 10:01

evanmcdonnal


Assume you want getting index of word in the data of array

data := [...] {"one","two","three"}

or fixed length array

data := [3] {"one","two","three"}

create function

func indexOf(word string, data []string) (int) {
    for k, v := range data {
        if word == v {
            return k
        }
    }
    return -1
}

to get value from function above, to match the type, pass the array with array[:] like below

fmt.Println(indexOf("two", data[:]))
like image 38
moehandi Avatar answered Jan 13 '23 10:01

moehandi