text/template: space in map's key - templates

I have the following code (using text/template):
inventory := map[string]string{"name of the movie": "hello"}
tmpl, err := template.New("test").Parse("Movie name ") // I want to display "hello" there
if err != nil { panic(err) }
err = tmpl.Execute(os.Stdout, inventory)
if err != nil { panic(err) }
As you can see, there is spaces in my map's key name of the movie. How can I do in the parse argument to display hello (which is the value of name of the movie)?

Use the index function: Movie name: {{index . "name of the movie"}}
From the docs:
index
Returns the result of indexing its first argument by the
following arguments. Thus "index x 1 2 3" is, in Go syntax,
x[1][2][3]. Each indexed item must be a map, slice, or array.

Related

golang append to 2d slice

I'm trying to create slice of slices.
In all the examples the inner slices are integer based.
I'm trying to create a slice of string slices.
Example:
[
[Name1,State1,Tags.Owner1]
[Name2,State2,Tags.Owner2]
[Name3,State3,Tags.Owner3]
]
I'm trying to do it this way:
outerList := [][]string{}
i := 0
for _,c := range clusters {
input := &eks.DescribeClusterInput{
Name: aws.String(c),
}
resp,err := svc.DescribeCluster(input)
if err != nil {
errorOut(`clusterData function: `+err.Error())
}
record := resp.Cluster
data,_ := json.Marshal(record)
error := json.Unmarshal(data, &cluster)
if error != nil {errorOut(error.Error())}
innerList := [...]string{cluster.Name,cluster.Tags["Vsad"],cluster.Status}
outerList[string(i)] = innerList
}
I get the below error:
non-integer slice index string(i)
cannot use innerList (type [3]string) as type []string in assignment
I know in Python I can simply do:
outerList = list()
for c in cluster:
a = [c.Name,c.State,c.Tags.Owner]
outerList.append(a)
You can use append. Formatted as follows:
// make room for clusters
outerList := make([][]string, len(clusters))
// iterate and fill cluster data
for i, c := range clusters {
// some processing where cluster variable is setupped
// add new inner slice
outerList[i] = append(outerList[i], cluster.Name, cluster.Tags["Vsad"], cluster.Status)
}

Golang SplitAfter for Regexp type

In golang strings.SplitAfter method split text after an special character into an slice, but I didn't find a way for Regexp type to split text after matches. Is there a way to do that?
Example :
var text string = "1.2.3.4.5.6.7.8.9"
res := strings.Split(text, ".")
fmt.Println(res) // print [1 2 3 4 5 6 7 8 9]
res = strings.SplitAfter(text, ".")
fmt.Println(res) // print [1. 2. 3. 4. 5. 6. 7. 8. 9]
first at all, your regex "." is wrong for splitAfter function. You want number followed by value "." so the regex is: "[1-9]".
The function you are looking might look like this:
func splitAfter(s string, re *regexp.Regexp) (r []string) {
re.ReplaceAllStringFunc(s, func(x string) string {
s = strings.Replace(s,x,"::"+x,-1)
return s
})
for _, x := range strings.Split(s,"::") {
if x != "" {
r = append(r, x)
}
}
return
}
Than:
fmt.Println(splitAfter("healthyRecordsMetric",regexp.MustCompile("[A-Z]")))
fmt.Println(splitAfter("healthyrecordsMETetric",regexp.MustCompile("[A-Z]")))
fmt.Println(splitAfter("HealthyHecord Hetrics",regexp.MustCompile("[A-Z]")))
fmt.Println(splitAfter("healthy records metric",regexp.MustCompile("[A-Z]")))
fmt.Println(splitAfter("1.2.3.4.5.6.7.8.9",regexp.MustCompile("[1-9]")))
[Healthy Records Metric]
[healthy Records Metric]
[healthyrecords M E Tetric]
[Healthy Hecord Hetrics]
[healthy records metric]
[1. 2. 3. 4. 5. 6. 7. 8. 9]
Good luck!
Regexp type itself does not have a method to do that exactly that but it's quite simple to write a function that implements what your asking based on Regexp functionality:
func SplitAfter(s string, re *regexp.Regexp) []string {
var (
r []string
p int
)
is := re.FindAllStringIndex(s, -1)
if is == nil {
return append(r, s)
}
for _, i := range is {
r = append(r, s[p:i[1]])
p = i[1]
}
return append(r, s[p:])
}
Here I left a program to play with it.

How to update field value in a Go template

I have the following case, where I am passing a struct containing a map to a template:
package main
import (
"log"
"os"
"text/template"
)
var fns = template.FuncMap{
"plus1": func(x int) int {
return x + 1
},
}
type codec struct {
Names map[string]string
Count int
}
func main() {
a := map[string]string{"one": "1",
"two": "2",
"three": "3"}
t := template.Must(template.New("abc").Funcs(fns).Parse(`{{$l := len .Names}}{{range $k, $v := .Names}}{{if ne (plus1 $.Count) $l}}{{$k}} {{$v}} {{end}}{{end}}.`))
err := t.Execute(os.Stdout, codec{a, 0})
if err != nil {
log.Println(err)
}
}
I would like to increment the Count field of codec so that I can know how many items of the map I've seen.
One solution is to make the plus1 function a closure that acts directly on the value of the codec:
// first create a codec instance
c := codec {a, 0}
// now define the function as a closure with a reference to c
fns := template.FuncMap{
"plus1": func() int {
c.Count++
return c.Count
},
}
// now we don't need to pass anything to it in the template
t := template.Must(template.New("abc").Funcs(fns).Parse(`{{$l := len .Names}}{{range $k, $v := .Names}}{{if ne (plus1) $l}}{{$k}} {{$v}} {{end}}{{end}}.`))
The output was:
one 1 three 3
which I'm guessing is what you were aiming for? And the value is retained in c at the end of execution.
You can simply define a method on your struct:
type codec struct {
Names map[string]string
Count int
}
func (c *codec) IncAndGet() int {
c.Count++
return c.Count
}
Calling it from a template:
c := &codec{Count: 2}
t := template.Must(template.New("").Parse(`{{.IncAndGet}} {{.IncAndGet}}`))
t.Execute(os.Stdout, c)
Output (try it on the Go Playground):
3 4
Note that for this to work, the method needs a pointer receiver (func (c *codec) IncAndGet()) and you have to pass a pointer to Template.Execute() (c is a pointer in our example: c := &codec{Count: 2}).
If you don't want any result just counting, define it to have a string return type and return the empty string "":
func (c *codec) Inc() string {
c.Count++
return ""
}

Pascal - doubly linket list

I'm trying compile Doubly linked list but I have one small problem with this part of code :
It's a "insert after"
When I insert data to the list : 1 2 3 4 5 and want insert after number 4 for example number 9, number 9 is inserted like this : 1 9 2 3 4 5. I really dont know where I have wrong code:(
everytime i insert new number to second position..
procedure insertAfter(var L:Plist; n_p:integer);
var novy_za:Plist;
begin
new(novy_za);
novy_za^.info:=n_p;
novy_za^.next:=L^.next;
novy_za^.prev:=L;
L^.next:=novy_za;
if novy_za^.next<>nil
then novy_za^.next^.prev:=novy_za;
end;
procedure call :
begin
writeln;
write('which number insert : '); readln(x);
writeln;
write('insert after : '); readln(Y);
InsertAfter(P,x);
end;
Here's a corrected version of your routine. Your original failed to accept the value you want to insert after as an argument. I made it a function so that it returns the pointer to the new added element if it was able to find the one you wanted to insert after. Otherwise, it returns nil. You call it with a second argument which tells it what value you want to insert after.
function insertAfter(var L: Plist; n_a, n_p: integer): Plist;
var novy_za, cur_za: Plist;
begin
cur_za := L;
novy_za := nil;
{ Traverse the list, looking for value n_a and, if found, insert the new
element n_p after it }
while cur_za <> nil do begin
{ Insert the new element after the one with value n_a }
if cur_za^.info = n_a then begin
new(novy_za);
novy_za^.info := n_p;
novy_za^.next := cur_za^.next;
novy_za^.prev := cur_za;
cur_za^.next := novy_za;
if novy_za^.next <> nil then
novy_za^.next^.prev := novy_za;
break; { Exit the loop }
end;
cur_za := cur_za^.next;
end;
insertAfter := novy_za;
end;
Function call (this assumes P is defined somewhere as a valid Plist, and x and y are defined as info type):
begin
writeln;
write('which number insert : '); readln(x);
writeln;
write('insert after : '); readln(y);
{ Insert the value x after the number y }
if insertAfter(P, y, x) = nil then
writeln('The value ', y, ' was not found')
else
writeln('The value ', x, ' was successfully inserted after ', y);
end;

Search for an item in a Lua list

If I have a list of items like this:
local items = { "apple", "orange", "pear", "banana" }
how do I check if "orange" is in this list?
In Python I could do:
if "orange" in items:
# do something
Is there an equivalent in Lua?
You could use something like a set from Programming in Lua:
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
Then you could put your list in the Set and test for membership:
local items = Set { "apple", "orange", "pear", "banana" }
if items["orange"] then
-- do something
end
Or you could iterate over the list directly:
local items = { "apple", "orange", "pear", "banana" }
for _,v in pairs(items) do
if v == "orange" then
-- do something
break
end
end
Use the following representation instead:
local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
...
end
You're seeing firsthand one of the cons of Lua having only one data structure---you have to roll your own. If you stick with Lua you will gradually accumulate a library of functions that manipulate tables in the way you like to do things. My library includes a list-to-set conversion and a higher-order list-searching function:
function table.set(t) -- set of list
local u = { }
for _, v in ipairs(t) do u[v] = true end
return u
end
function table.find(f, l) -- find element v of l satisfying f(v)
for _, v in ipairs(l) do
if f(v) then
return v
end
end
return nil
end
Write it however you want, but it's faster to iterate directly over the list, than to generate pairs() or ipairs()
#! /usr/bin/env lua
local items = { 'apple', 'orange', 'pear', 'banana' }
local function locate( table, value )
for i = 1, #table do
if table[i] == value then print( value ..' found' ) return true end
end
print( value ..' not found' ) return false
end
locate( items, 'orange' )
locate( items, 'car' )
orange found
car not found
Lua tables are more closely analogs of Python dictionaries rather than lists. The table you have create is essentially a 1-based indexed array of strings. Use any standard search algorithm to find out if a value is in the array. Another approach would be to store the values as table keys instead as shown in the set implementation of Jon Ericson's post.
This is a swiss-armyknife function you can use:
function table.find(t, val, recursive, metatables, keys, returnBool)
if (type(t) ~= "table") then
return nil
end
local checked = {}
local _findInTable
local _checkValue
_checkValue = function(v)
if (not checked[v]) then
if (v == val) then
return v
end
if (recursive and type(v) == "table") then
local r = _findInTable(v)
if (r ~= nil) then
return r
end
end
if (metatables) then
local r = _checkValue(getmetatable(v))
if (r ~= nil) then
return r
end
end
checked[v] = true
end
return nil
end
_findInTable = function(t)
for k,v in pairs(t) do
local r = _checkValue(t, v)
if (r ~= nil) then
return r
end
if (keys) then
r = _checkValue(t, k)
if (r ~= nil) then
return r
end
end
end
return nil
end
local r = _findInTable(t)
if (returnBool) then
return r ~= nil
end
return r
end
You can use it to check if a value exists:
local myFruit = "apple"
if (table.find({"apple", "pear", "berry"}, myFruit)) then
print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1
You can use it to find the key:
local fruits = {
apple = {color="red"},
pear = {color="green"},
}
local myFruit = fruits.apple
local fruitName = table.find(fruits, myFruit)
print(fruitName) -- "apple"
I hope the recursive parameter speaks for itself.
The metatables parameter allows you to search metatables as well.
The keys parameter makes the function look for keys in the list. Of course that would be useless in Lua (you can just do fruits[key]) but together with recursive and metatables, it becomes handy.
The returnBool parameter is a safe-guard for when you have tables that have false as a key in a table (Yes that's possible: fruits = {false="apple"})
function valid(data, array)
local valid = {}
for i = 1, #array do
valid[array[i]] = true
end
if valid[data] then
return false
else
return true
end
end
Here's the function I use for checking if data is in an array.
Sort of solution using metatable...
local function preparetable(t)
setmetatable(t,{__newindex=function(self,k,v) rawset(self,v,true) end})
end
local workingtable={}
preparetable(workingtable)
table.insert(workingtable,123)
table.insert(workingtable,456)
if workingtable[456] then
...
end
The following representation can be used:
local items = {
["apple"]=true, ["orange"]=true, ["pear"]=true, ["banana"]=true
}
if items["apple"] then print("apple is a true value.") end
if not items["red"] then print("red is a false value.") end
Related output:
apple is a true value.
red is a false value.
You can also use the following code to check boolean validity:
local items = {
["apple"]=true, ["orange"]=true, ["pear"]=true, ["banana"]=true,
["red"]=false, ["blue"]=false, ["green"]=false
}
if items["yellow"] == nil then print("yellow is an inappropriate value.") end
if items["apple"] then print("apple is a true value.") end
if not items["red"] then print("red is a false value.") end
The output is:
yellow is an inappropriate value.
apple is a true value.
red is a false value.
Check Tables Tutorial for additional information.
function table.find(t,value)
if t and type(t)=="table" and value then
for _, v in ipairs (t) do
if v == value then
return true;
end
end
return false;
end
return false;
end
you can use this solution:
items = { 'a', 'b' }
for k,v in pairs(items) do
if v == 'a' then
--do something
else
--do something
end
end
or
items = {'a', 'b'}
for k,v in pairs(items) do
while v do
if v == 'a' then
return found
else
break
end
end
end
return nothing
A simple function can be used that :
returns nil, if the item is not found in table
returns index of item, if item is found in table
local items = { "apple", "orange", "pear", "banana" }
local function search_value (tbl, val)
for i = 1, #tbl do
if tbl[i] == val then
return i
end
end
return nil
end
print(search_value(items, "pear"))
print(search_value(items, "cherry"))
output of above code would be
3
nil