Check empty struct that have array fields - arrays

I have a nested (not embedded) struct for which some of field types are arrays.
How can I check if an instance of this struct is empty? (not using iteration!!)
Note that there can't use StructIns == (Struct{}) or by an empty instance! This code have this error:
invalid operation: user == model.User literal (struct containing model.Configs cannot be compared)
user.Configs.TspConfigs:
type TspConfigs struct {
Flights []Flights `form:"flights" json:"flights"`
Tours []Tours `form:"tours" json:"tours"`
Insurances []Insurances`form:"insurances" json:"insurances"`
Hotels []Hotels `form:"hotels" json:"hotels"`
}

Those are slices, not arrays. It's important to emphasize as arrays are comparable but slices are not. See Spec: Comparision operators. And since slices are not comparable, structs composed of them (structs with fields having slice types) are also not comparable.
You may use reflect.DeepEqual() for this. Example:
type Foo struct {
A []int
B []string
}
f := Foo{}
fmt.Println("Zero:", reflect.DeepEqual(f, Foo{}))
f.A = []int{1}
fmt.Println("Zero:", reflect.DeepEqual(f, Foo{}))
Output (try it on the Go Playground):
Zero: true
Zero: false

Related

Golang for loop with multiple brackets

I've stumbled upon this repository,
https://github.com/prometheus-community/jiralert/blob/a0f0e80e575e71cbf7db565d3296a3a984282dff/pkg/config/config_test.go#L148
The for loop has multiple brackets:
for _, test := range []struct {
missingField string
errorMessage string
}{
{"Name", "missing name for receiver"},
(...)
} {
fields := removeFromStrSlice(mandatory, test.missingField)
(...)
}
configErrorTestRunner(t, config, test.errorMessage)
}
I haven't been able to find anything about this in the go documentation, what is this construct?
The first bracket pair is part of the struct type definition which has the syntax:
struct{
field1 type1
field2 type2
...
}
The second pair is part of the composite literal value, creating a value for the slice of this struct. It has the syntax of:
[]elementType{value1, value2, ...}
The inner, embedded brackets are part of the composite literals creating the struct values of the slice. The type is omitted (it's known from the slice type), so each {field1Value, fieldValue2...} is a struct value.
The third pair defines the block of the for statement. The for statement iterates over the elements of the slice defined by the mentioned composite literal.
To clean up the code for better readability and understanding. Whatever you gave was equivalent to:
type TestStruct struct {
missingField string
errorMessage string
}
testCase := TestStruct {
{
missingField: "Name",
errorMessage: "missing name for receiver",
}
(...)
}
for _, test := range(testCase) {
fields := removeFromStrSlice(mandatory, test.missingField)
}
configErrorTestRunner(t, config, test.errorMessage) is probably from a parent test func

Difference between initialization of struct slices

type Person struct {
ID int `json:"id"`
}
type PersonInfo []Person
type PersonInfo2 []struct {
ID int `json:"id"`
}
Is there have difference between PersonInfo (named slice of named structs) and PersonInfo2 (named slice of unnamed structs)
The main difference is how you have to initialize Person objects outside of the PersonInfo/PersonInfo2 initialization. Since PersonInfo2 is an array of the anonymous struct type we know nothing about this type outside of the PersonInfo2 initialization.
So they can both be initialized like this:
m := PersonInfo{{1}, {2}}
n := PersonInfo2{{1},{2}}
However if we want to append an element of the anonymous struct type we would have to specify the full type:
append(n, struct { ID int `json:"id"` }{3})
If we print these out we can see they appear to be the same:
fmt.Printf("%+v\n%+v", m, n)
Outputs:
[{ID:1} {ID:2}]
[{ID:1} {ID:2}]
However they wont be deeply equal because PersonInfo is an array of type Person and PersonInfo2 is an array of anonymous struct type. So the following:
if !reflect.DeepEqual(m,n) {
print("Not Equal")
}
will print "Not Equal".
Here is a link to see for yourself.
When appending to PersonInfo2 we have to repeat the anonymous struct type for every value we want to append, it is probably better to use PersonInfo as an array of type Person.
Go is using structural typing, that means, as long as the two types have the same underlying type, they are equivalent.
So, for your question: Person and struct{ ID int 'json:"id"'} is equivalent because they have the same underlying type, and therefore, PersonInfo and PersonInfo2 are also equivalent. I took of the json tags to simplify the example.
person1 := Person{1}
pStruct1 := struct{ID int}{2}
pInfo1 := PersonInfo{
person1,
pStruct1,
}
pInfo2 := PersonInfo2{
person1,
pStruct1,
}
fmt.Printf("%+v\n", pInfo1)
fmt.Printf("%+v", pInfo2);
//outputs
//PersonInfo: [{ID:1} {ID:2}]
//PersonInfo2: [{ID:1} {ID:2}]
Code example: https://play.golang.org/p/_wlm_Yfdy2
type PersonInfo is an object of Person, while PersonInfo2 is a class (or type in Golang) by itself. Even though their data structure is similar.
So, when you run DeepEqual() to check the similarity it will turn out to be false.
Example by previous comment:
if !reflect.DeepEqual(m,n) {
print("Not Equal")
}
Hope this helps.

Swift Array of Self-defined Objects Contains: Requires to Insert 'where:'

Hi I'm new to Swift and I'm trying to implement a Graph structure. I have defined Node and Edge structs, and now I'm trying to check whether a particular edge exists in the graph or not. The class and related function is like this:
class Graph<T: Equatable> {
private var storedNodes = [Node]()
private var storedEdges = [Edge]()
func containsSimpleGraphEdge(targetEdge: Edge) -> Bool {
let simpleGraphEdges = self.storedEdges.map({edge in (edge.source, edge.dest)})
let targetSimpleGraphEdge = (targetEdge.source, targetEdge.dest)
return simpleGraphEdges.contains(targetSimpleGraphEdge)
}
But Xcode is complaining that I should insert 'where: ' in the last contains statement. May I know why it's like this? My purpose is just to check whether an edge exists in the graph or not. The mapping to tuples is done because in the Edge implementation there are other properties; here only the source node and the destination node need to be checked.
But Xcode is complaining that I should insert where: in the last
contains statement. May I know why it's like this?
As pointed out by #Keiwan below, tuples don't conform to Equatable, even if Swift's standard lib provides us with equality testing operator == for tuples up to 6 members, given that all members themselves conform to Equatable; the latter as described in the following Swift Evolution proposal:
Se-0015: Tuple comparison operators
Hence, your attempted call to contains(_:) fails as this method is not accessible for non-Equatable elements.
You could, however, make use of contains(where:) to explicitly provide a closure telling contains how to test equality. Given that your Node type conforms to Equatable, you'll want to modify the contains call in the return of your method into:
return simpleGraphEdges.contains(where: { $0 == targetSimpleGraphEdge })
// note also your typo here, 'targetSimpleEdge' should be 'targetSimpleGraphEdge'
Or, supplying the predicate as a trailing closure:
return simpleGraphEdges.contains { $0 == targetSimpleGraphEdge }
If you don't want to make Edge equatable (such as when it has multiple context-dependant definitions of "equality"), you can just use contains(where:).
func contains(simpleGraphEdge e: Edge) -> Bool {
return self.storedEdges.contains(where: {
$0.source == e.source && $0.dest == e.dest
})
}

Nilable value in appengine/datastore using Go

The list of supported types by datastore doesn't contain pointer types (https://cloud.google.com/appengine/docs/go/datastore/reference).
How then can I represent a value that can and sometimes should be nil?
For example in the following structure I need the DailyValuePercent to be nilable to explicitly say that the value is missing.
type NutritionFact struct {
Name string `datastore:",noindex" json:"name"`
DailyValuePercent int `datastore:",noindex" json:"dailyValuePercent"`
}
Since I can't use *int as the field type for datastore then how to represent an optional value?
Either store your ints as strings (with empty string => no value) or use a composite type like:
type NillableInt struct {
i int
isNil bool // or isNotNil bool if you want different default semantics
}
Adapt to your performance vs. memory usage requirements.
If you want your code to deal with int pointers but persist nil values in the datastore, define your struct like this:
type NutritionFact struct {
Name string `datastore:",noindex" json:"name"`
DailyValuePercent int `datastore:"-"`
}
And implement the PropertyLoadSaver interface where you will save/load an int value and a isNil boolean.

Sort "array" of mixed data type in C

I have a continuous block of memory, where the first N bytes all contain objects of type A and the remaining bytes contain elements of type B. So for example, I might have 120 objects of type A followed by 40 objects of type B.
Type A and type B are both structures with different sizes, but both have an integer member "index" which is what I want to sort on. Basically I want to end up with an array that is sorted on index and I currently have one which is sorted on data type. Ideally, I'd like to end up with it sorted on index, then by type, so something like
Index==1 elements | Index==2 elements | ... | Index==L elements
Type A | Type B | Type A | Type B | ... | Type A| Type B
The only thing I've come up with so far is to sort the type A and type B blocks separately by index and then use memcopy to shuffle things around so they look like above. Is there a better solution?
How is the original array set up? Mixing different types in the same array seems like a bad idea. Is there a reason you need to have them in the same array?
If they must be in the same array you might want to use a union. Something like
enum myType { A, B };
struct typeA { myType type; int key; ... data ... }
struct typeB { myType type; int key; ... data ... }
union myTypes { typeA myA; typeB myB }
myTypes data[128];
You can now use the qsort function from the C library.
Another option would be to use a separate array of pointers to the objects and then sort that auxilary array. You would still need some kind of type field at the beginning of each struct though.
Instead of pointers as suggested, you might want to use a struct consisting of type and pointer (the latter even as a union of two different pointers). In this case, you can easily distinguish which type the objects are - unless they nevertheless have the ID field at the same place.
So suppose you have
struct typeA {
int whatever;
int id;
}
struct typeB {
double whatever;
int id;
}
you are bitten and have to do as I stated:
struct typptr {
enum type { typ_A, typ_B } type;
union {
struct typeA * Aptr;
struct typeB * Bptr;
}
}
int getID(struct typptr t)
{
if (t.type == typ_A) {
return (t.Aptr)->id * 2;
} else {
return (t.Bptr)->id * 2 + 1; // have B always sorted after A...
}
}
This way you can easily write a cmp function for qsort in order to sort the struct typptrs.
If the types are "shaped similiarly", such as
struct typeA {
int id;
int whatever;
}
struct typeB {
int id;
double whatever;
}
i.e. have the id field at the start, things are easier (but I don't know if this is portable) as you can always cast to one of them and read out the id field. So you only need an array of pointers and can omit the type field.
There's important information in your later comment - the types aren't initially mixed.
If so, you could run a sort phase on each array part individually (quicksort or any other method you'd like), and then do a final phase of merge-sort between the two arrays (assuming you can spare the additional space)
that's still NlogN + N = NlogN

Resources