Douglas Fils
Douglas Fils

Reputation: 311

Find all matches in Go array

I have an array of structs (struct detailed at bottom)

I want to find all the structs that match certain values for, example, leg and site.

So if leg=101 and site=1024A give back all the structs that match these criteria.

What is the Go manner for doing this?

type JanusDepth struct {
    dataset string
    ob      string
    leg     string  
    site    string  
    hole    string
    age     float64
    depth   float64
    long    float64
    lat     float64
}

Upvotes: 6

Views: 7368

Answers (3)

ChickenMcNuggets
ChickenMcNuggets

Reputation: 29

More than 10 years later, I'm wondering why I can't find anything better than a manual for loop in order to filter some data from a list. I've came to create custom helper functions for this, as follows:

// Filter the slice based on the predicate and return the result
func filter[S ~[]T, T any](slice S, predicate func(T) bool) []T {
    out := make([]T, 0)

    for _, item := range slice {
        if predicate(item) {
            out = append(out, item)
        }
    }

    return out
}

// For cases where you have to filter the slice and also keep the items that do not match the predicate
func filterOr[S ~[]T, T any](slice S, predicate func(T) bool) ([]T, []T) {
    out := make([]T, 0)
    orOut := make([]T, 0)

    for _, item := range slice {
        if predicate(item) {
            out = append(out, item)
        } else {
            orOut = append(orOut, item)
        }
    }

    return out, orOut
}

They can then be used like this:

package main

import "fmt"

func isEven(num int) bool { return num%2 == 0 }

func main() {
    initialSlice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    evenNumbers1 := filter(initialSlice, isEven)

    // Even numbers: [2 4 6 8 10]
    fmt.Printf("Even numbers: %v\n", evenNumbers1)

    evenNumbers2, oddNumbers := filterOr(initialSlice, isEven)

    // Even numbers: [2 4 6 8 10]
    fmt.Printf("Even numbers: %v\n", evenNumbers2)
    // Odd numbers: [1 3 5 7 9]     
    fmt.Printf("Odd numbers: %v\n", oddNumbers)
}

Thanks to this, my code is a little less bloated.

Upvotes: 0

Jeff Allen
Jeff Allen

Reputation: 1471

If your data is ordered on one key, then you can use http://golang.org/pkg/sort/#Search to do a binary search, which is better for performance if the amount of data is moderate to large.

Upvotes: 2

thwd
thwd

Reputation: 24818

Dead simple:

leg      := "101"
site     := "1024A"
filtered := []JanusDepth{}

for _, e := range MyArrayOfStructs {
    if(e.leg == leg && e.site == site) {
        filtered = append(filtered, e)
    }
}

// filtered contains your elements

Upvotes: 10

Related Questions