Populating a priority queue based off boolean conditionals - go

I have a slice that I have to place 5 groupings of entries in.
I have to order everything relative to a one of the groups. So for example there is the base grouping and then each additional group placement is decided by a boolean, so true it needs to be appended or false prepended.
I can do this through a long and nasty looking block of if...else statements, but wondering if there is a better way I can do this semantically? Or an alternative method I should be using for the conditional that can help with this (each grouping can be of a couple or thousands of individual related entries that would be spread out). The final result needs to be a slice, as input into the configuration struct where it lives needs to be a slice.
func buildNewRoutesQueue(overrideGroup1 bool, overrideGroup2 bool, overrideGroup3 bool, overrideGroup4 bool, baseRoutes []*route.Route) []*route.Route {
var result []*route.Route
if overrideGroup1 {
result = append(routes.GetGroup1Routes(), baseRoutes...)
} else {
result = append(baseRoutes, routes.GetGroup1Routes()...)
}
if overrideGroup1 {
result = append(routes.GetGroup2Routes(), result...)
} else {
result = append(result, routes.GetGroup2Routes()...)
}
if overrideGroup3 {
result = append(routes.GetGroup3Routes(), result...)
} else {
result = append(result, routes.GetGroup3Routes()...)
}
if overrideGroup4 {
result = append(routes.GetGroup4Routes(), result...)
} else {
result = append(result, routes.GetGroup4Routes()...)
}
return result
}
Are there any performance issues here, and is there a better semantic way of doing this than what Im thinking? I can replace the boolean conditional with anything, its not set in stone.

Related

unable to break out of outer loop in golang

the following is my function where im trying to Validate the ID's and unable to return values from the inner loop.
func Validate(id int, tn []Node) int {
var value int
for _, j := range tn {
if id == j.ID {
println(id, j.ID)
value = j.ID
println("aa", value)
break
} else {
if j.Children != nil {
ValidateID(id, j.Children)
}
}
}
return value
}
It looks like you want to return whether the ID was found in any node of a tree. Your code is almost there, but you need to check whether the recursive call finds it. Using return rather than break makes the code simpler.
I removed the print statements, which I guess are there for debugging purposes.
I also replaced the return value with a bool (the original code either returned the ID itself or 0 to represent not-found), and removed the j.Children == nil test (the code returns false for an empty slice:
// ValidateID reports whether id exists in a tree of nodes.
func ValidateID(id int, tn []Node) bool {
for _, j := range tn {
if id == j.ID || ValidateID(id, j.Children) {
return true
}
}
return false
}
Note if you want to actually return something other than a bool from the target node, I'd make the function return two values: that which you are interested and the bool that says whether the ID was found. Relying on sentinel values like 0 is discouraged by "Effective Go".

Idiomatic and DRY solution to merging arrays of arbitrary types

I want to create a utility-function that is able to merge two given slices, determining equality by a given function.
type IsEqualTest func(interface{}, interface{}) bool
func ArrayMerge(one *[]interface{}, another *[]interface{}, comp IsEqualTest) *[]interface{} {
merged := *one
for _, element := range *another {
if !ArrayContains(one, &element, comp) {
merged = append(merged, element)
}
}
return &merged
}
func ArrayContains(container *[]interface{}, eventualContent *interface{}, comp IsEqualTest) bool {
for _, element := range *container {
if comp(element, eventualContent) {
return true
}
}
return false
}
// please don't mind the algorithmic flaws
However, as go does treat the []interface{} type as non-compatible to slices of anything (and it lacks generics), I would need to iterate over both operands, converting the type of the contained elements when calling, which is not what anyone could want.
What is the Go style of dealing with collections containing any type?
First: without generics, there is no idiomatic way of doing this.
Second: your thinking might be too influenced by other languages. You already got a function to compare, why not take it a bit further?
What I suggest below is not efficient, and it should not be done. However, if you really want to do it:
It looks like this is not a set union, but add the elements of the second slice to the first if they don't already exist in the first slice. To do that, you can pass two functions:
func merge(len1,len2 int, eq func(int,int)bool, write func(int)) {
for i2:=0;i2<len2;i2++ {
found:=false
for i1:=0;i1<len1;i1++ {
if eq(i1,i2) {
found=true
break
}
}
if !found {
write(i2)
}
}
Above, eq(i,j) returns true if slice1[i]==slice2[j], and write(j) does append(result,slice2[j]).

Check if every item in a struct is unchanged

I have the following package:
// Contains state read in from the command line
type State struct {
Domain string // Domain to check for
DomainList string // File location for a list of domains
OutputNormal string // File to output in normal format
OutputDomains string // File to output domains only to
Verbose bool // Verbose prints, incl. Debug information
Threads int // Number of threads to use
NoColour bool // Strip colour from output
Silent bool // Output domains only
Usage bool // Print usage information
}
func InitState() (state State) {
return State { "", "", "", "", false, 20, false, false, false }
}
func ValidateState(s *State) (result bool, error string ) {
if s.Domain == "" && s.DomainList == "" {
return false, "You must specify either a domain or list of domains to test"
}
return true, ""
}
Within ValidateState() I would like to return true if every item in State is the same as what is defined in InitState(). I can see a few ways to do this, but nothing that seems concise. I would greatly value some direction!
Struct values are comparable if all their fields are comparable (see Spec: Comparison operators). And since in your case this holds, we can take advantage of this.
In your case the simplest and most efficient way to achieve this is to save a struct value holding the initial value, and whenever you want to tell if a struct value (if any of its fields) has changed, simply compare it to the saved, initial value. This is all it takes:
var defaultState = InitState()
func isUnchanged(s State) bool {
return s == defaultState
}
Testing it:
s := InitState()
fmt.Println(isUnchanged(s))
s.Threads = 1
fmt.Println(isUnchanged(s))
Output (try it on the Go Playground):
true
false
Note that this solution will still work without any modification if you change the State type by adding / removing / renaming / rearranging fields as long as they all will still be comparable. As a counter example, if you add a field of slice type, it won't work anymore as slices are not comparable. It will result in a compile-time error. To handle such cases, reflect.DeepEqual() might be used instead of the simple == comparison operator.
Also note that you should create default values of State like this:
func NewState() State {
return State{Threads: 20}
}
You don't have to list fields whose values are the zero values of their types.

Should true or false terminate callback iteration?

In some languages it's necessary or cleaner to do iteration by providing a callback function that receives items and returns a boolean that indicates whether to continue or stop the iteration.
Which is the preferred value to indicate desire to stop/continue? Why? What precedents exist?
Example in Go:
func IntSliceEach(sl []int, cb func(i int) (more bool)) (all bool) {
for _, i := range sl {
if !cb(i) {
return false
}
}
return true
}
Which is the preferred value to indicate desire to stop/continue?
true for continue
Why?
Example 1:
func example(i interface{}) {
if w, ok := i.(io.Writer); ok {
// do something with your writer, ok indicates that you can continue
}
}
Example 2:
var sum int = 0
it := NewIntStatefulIterator(int_data)
for it.Next() {
sum += it.Value()
}
In both cases true (ok) indicates that you should continue. So I assume that it would be way to go in your example.
Foreword: The following answer applies to a callback function which decides based on the current item(s) whether the loop should terminate early - this is what you asked.
This is not to be confused with a function that progresses and reports if there are more elements to process, where a true return value is generally accepted to signal that there are more elements (for which a good example is Scanner.Scan()), and whose typical use is:
scanner := bufio.NewScanner(input)
for scanner.Scan() {
// Process current item (line):
line := scanner.Text()
fmt.Println(line) // Do something with line
}
Sticking to bool return type
Usually returning true to indicate termination results in code that is easier to read. This is due to the nature of for: if you do nothing, for continues, so you have to explicitly break if you want to terminate early, so having a clean termination condition is more common.
But it's a matter of taste. You may go whichever you like, but what's important is to name your callback function in a meaningful way that will clearly state what its return value means, and thus looking at the code (the condition in which it is used) will be easily understandable.
For example the following names are good and the return value is unambiguous:
// A return value of true means to terminate
func isLast(item Type) bool
func terminateAfter(item Type) bool
func abort(item Type) bool
// A return value of true means to continue (not to terminate)
func keepGoing(item Type) bool
func carryOn(item Type) bool
func processMore(item Type) bool
Using these results in easily understandable code:
for i, v := range vals {
doSomeWork()
if terminateAfter(v) {
break // or return
}
}
for i, v := range vals {
doSomeWork()
if !keepGoing(v) {
break // or return
}
}
// Or an alternative to the last one (subjective which is easier to read):
for i, v := range vals {
doSomeWork()
if keepGoing(v) {
continue
}
break
}
As negative examples, the following callback function names are bad as you can't guess what their return value mean:
// Bad: you can't tell what return value of true means just by its name:
func test(item Type) bool
func check(item Type) bool
Having error return type
It's also common for the callback to not just test but also do some work with the passed item. In these cases it is meaningful to return an error instead of a bool. Doing so, obviously the nil return value indicates success (and to continue), and a non-nil value indicates error and that processing should stop.
func process(item Type) error
for i, v := range vals {
if err := process(v); err != nil {
// Handle error and terminate
break
}
}
Having enum-like return value
Also if multiple return values have meaning, you may choose to define constants for return values, which you can name meaningfully.
type Action int
const (
ActionContinue Action = iota
ActionTerminate
ActionSkip
)
func actionToTake(item Type) Action
for i, v := range vals {
switch actionToTake(v) {
case ActionSkip:
continue
case ActionTerminate:
return
}
doSomeWork()
}

The Swift Programming Language Enumerations Experiment

I'm making my way through The Swift Programming Language book, but I'm stuck on an experiment.
I'm given this code:
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "Ace"
case .Jack:
return "Jack"
case .Queen:
return "Queen"
case .King:
return "King"
default:
return String(self.toRaw())
}
}
}
For the experiment, I have to "Write a function that compares two Rank values by comparing their raw values.
I had a go:
func rankCompare(first: String, second: String) -> String {
let firstRank = Rank.first
}
But I ended up with errors because I don't know how to pass Enum values.
Can someone help?
Enum values can be passed just like other types. The following function is part of the Rank enum and compares one Rank to another.
func compareToOther(other:Rank) -> Bool { // other is of type Rank
return self.toRaw() == other.toRaw()
}
Here is a screenshot of the quick implementation and usage.
You can pass enums by just passing the enum name:
// someRank is a Rank enum value
func myFunction (someRank: Rank) -> () {
}
And then you can just call it:
myFunction(Rank.Ace)
I am also a beginner, but this is how I worked throughout the experiment. First I added this;
func compareTwoCards(card1: Rank, card2: Rank) -> String {
if card1.toRaw() == card2.toRaw() {
return "Cards are equal"
} else {
if card1.toRaw() > card2.toRaw() {
return "Card1 is greater"
} else {
return "Card2 is greater"
}
} }
Then I created two Rank objects
let ace = Rank.Ace
let queen = Rank.Queen
Finally, I called it three different ways to test it;
compareTwoCardsTake2(ace, queen)
compareTwoCardsTake2(queen, ace)
compareTwoCardsTake2(ace, ace)
Can some one with more experience please reply if there is a better/more elegant way of performing the compare?
I solved it like this:
func rankCompare(first: Rank, second: Rank) -> String {
if(first.rawValue > second.rawValue) {
return "\(first.simpleDescription()) beats \(second.simpleDescription())."
}
else if second.rawValue > first.rawValue {
return "\(second.simpleDescription()) beats \(first.simpleDescription())."
}
else {
return "\(first.simpleDescription()) equals \(second.simpleDescription())."
}
}
let king = Rank.King
let queen = Rank.Queen
let seven = Rank.Seven
rankCompare(king, queen)
rankCompare(seven, king)
rankCompare(queen, queen)
Use .rawValue for doing the comparisons and .simpleDescription() for writing out your answer.
This code can be used to determine if two enumeration values are equal or not. .toRaw() is obsolete, so .rawValue must be used to obtain the raw value for comparison. An edited version of this function (to make a full comparison with type string information, not just "true" or "false") should be used to complete the exercise. Hint For Editing: this function is of type Bool.
func compareRanks(rankA: Rank, rankB: Rank) -> Bool {
return rankA.rawValue == rankB.rawValue
}
To see the code and contributors that made this answer possible, please see the question: Explanation of The Swift Programming Language Enumerations Experiment

Resources