在Golang中,根据不同的切片对结构体切片进行过滤。

huangapple go评论80阅读模式
英文:

Filtering a slice of structs based on a different slice in Golang

问题

在下面的示例代码中,我有一些在manySimpleUsers中的用户,我想根据用户名从manyFullUsers中删除这些用户。

如果我使用嵌套的for...range循环来完成,那么在过滤所有元素时将需要很多循环,特别是当两个切片中的元素数量很大时。

在Go语言中,最好的方法是什么?

package main

import "fmt"

func main() {
    fmt.Println("Hello, playground")

    type FullUser struct {
        UserName  string
        UserEmail string
    }

    manyFullUsers := []FullUser{{"foo", "foo@jawohl.com"},
        {"bar", "bar@jawohl.com"},
        {"baz", "baz@jawohl.com"}}

    type SimpleUser struct {
        UserName string
    }

    manySimpleUsers := []SimpleUser{{"foo"}, {"bar"}}

    fmt.Println(manyFullUsers)
    fmt.Println(manySimpleUsers)
}
英文:

In the example code below, I have a few users in manySimpleUsers that I would like to remove from manyFullUsers based on the Username.

If I do it with a nested couple of for... range loops, there will be many cycles required to filter all of the elements, especially when there are large numbers of elements in both Slices.

What is the best way to achieve this in Go?

package main

import "fmt"

func main() {
	fmt.Println("Hello, playground")

	type FullUser struct {
		UserName  string
		UserEmail string
	}

	manyFullUsers := []FullUser{{"foo", "foo@jawohl.com"},
		{"bar", "bar@jawohl.com"},
		{"baz", "baz@jawohl.com"}}

	type SimpleUser struct {
		UserName string
	}

	manySimpleUsers := []SimpleUser{{"foo"}, {"bar"}}

	fmt.Println(manyFullUsers)
	fmt.Println(manySimpleUsers)
}

答案1

得分: 11

创建一个地图,然后使用它进行过滤。

func filterByUserName(fu []FullUser, su []SimpleUser) (out []FullUser) {
    f := make(map[string]struct{}, len(su))
    for _, u := range su {
        f[u.UserName] = struct{}{}
    }
    for _, u := range fu {
        if _, ok := f[u.UserName]; ok {
            out = append(out, u)
        }
    }
    return
}

playground

英文:

Create a map then use it to filter.

func filterByUserName(fu []FullUser, su []SimpleUser) (out []FullUser) {
	f := make(map[string]struct{}, len(su))
	for _, u := range su {
		f[u.UserName] = struct{}{}
	}
	for _, u := range fu {
		if _, ok := f[u.UserName]; ok {
			out = append(out, u)
		}
	}
	return
}

<kbd>playground</kbd>

答案2

得分: 1

你可以使用我创建的 https://github.com/ledongthuc/goterators 中的 Filter() 和 Exist() 函数来重用聚合和转换函数。

filteredFullUsers := goterators.Filter(manyFullUsers, func(item FullUser) bool {
    return !goterators.Exist(manySimpleUsers, SimpleUser{item.UserName})
})

你还可以从 manySimpleUsers 构建一个映射,这将有助于优化搜索用户名。

这个库需要 Go 1.18 版本以支持你想要使用的泛型和动态类型。

在Golang中,根据不同的切片对结构体切片进行过滤。

英文:

you can use Filter() and Exist() from https://github.com/ledongthuc/goterators that I created to reuse aggregate & transform functions.

在Golang中,根据不同的切片对结构体切片进行过滤。

	filteredFullUsers := goterators.Filter(manyFullUsers, func(item FullUser) bool {
		return !goterators.Exist(manySimpleUsers, SimpleUser{item.UserName})
	})

You also can build a map from manySimpleUsers that will be helpful to optimize searching username.

This lib requires the Go 1.18 to use that support generic + dynamic type you want to use with.

huangapple
  • 本文由 发表于 2015年9月30日 21:46:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/32867780.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定