当前位置: 首页 > 知识库问答 >
问题:

一种灵活而优雅的方式来排序Go中的结构片[关闭]

赵飞语
2023-03-14

假设我们有一个相当复杂的struct,有许多字段,我需要根据不同的标准在几个地方进行排序,例如。

type MySuperType struct {
    x0, x1, x2, x3 xType
    // possibly even more fields
}
// sort 1: ascending x0, then descending x1, then more stuff
// sort 2: if x4==0 then applyCriteria2a else applyCriteria2b

func f1(mySuperSlice []MySuperType) {
    // sort 'myList' according sort #1
    // do something with the sorted list
}
func f2(mySuperSlice []MySuperType) {
    // sort 'myList' according sort #2
    // do something with the sorted list
}
func f3(mySuperSlice []MySuperType) {
    // sort 'myList' according sort #1, note: we use sort #1 again!
    // do something with the sorted list
}

建议的解决方案1:
创建一个实现排序的新类型([]MySuperType的别名)。
问题:(i)有一些重复的代码,因为函数LenSwap是相同的(ii)会有一堆新的类型这对程序的整体可读性没有帮助——这些新类型并不能真正代表任何东西,另外唯一真正重要的是less函数。

建议的解决方案2:
使用排序。Slice
这将是一个完美的解决方案(请参见此答案),但据我所知,排序函数必须内联指定(我在别处尝试定义它时,得到一个错误无效的接收器类型[]T([]T为未命名类型),这意味着我需要为[]T定义一个别名,现在回到解决方案1)
现在,定义内联函数的问题是:(i)鉴于MySuperType的复杂性,函数可能非常长,(ii)函数将在多个位置重复(例如,在上面的示例中,在f1f3中)——由于排序函数可能很长且复杂,因此比解决方案1中的要烦人得多
注意:(i)如果我们没有(ii)实际

问题:
鉴于我目前对围棋的理解和知识,我会使用解决方案1
但是有人知道一种不同的方法可以优雅地解决这个问题吗?或者有人知道改进上面列出的缺点的建议吗?


共有3个答案

曹高轩
2023-03-14

您还可以省略额外的函数,并在需要时调用sort。

type MySuperType struct {
    x0, x1, x2, x3 string
}

func f1() {
    fields := []MySuperType {
        { "a1", "b4", "c3", "d2" },
        { "a2", "b1", "c2", "d3" },
        { "a3", "b1", "c4", "d1" },
        { "a4", "b3", "c1", "d4" },
    }
    sort.SliceStable(fields, func(i, j int) bool {
        return fields[i].x1 < fields[j].x1 || fields[i].x2 > fields[j].x2
    })
    fmt.Println("by x1, then x2: ", fields)
}

结果:x1,然后x2:[{a3 b1 c4 d1}{a2 b1 c2 d3}{a4 b3 c1 d4}{a1 b4 c3 d2}]

祁通
2023-03-14

@ThunderCat的解决方案将起作用。另一种选择是编写函数,在片上返回与sort的less参数的签名匹配的闭包。切片

func ascX0DescX1(s []MySuperType) (func(int, int) bool) {
    return func(i, j int) bool {
        if s[i].x0 == s[j].x0 {
            return s[i].x1 > s[j].x1
        }
        return s[i].x0 < s[j].x0
    }
}

然后将其作为lessarg传递给sort。切片

sort.Slice(mySuperSlice, ascX0DescX1(mySuperSlice))
东门宜
2023-03-14

为f1、f2和f3的每个排序和调用编写排序函数:

func sortByX0AscX1Desc(s []MySuperType) {
    sort.Slice(s, func(i, j int) bool {
        switch {
        case s[i].x0 < s[j].x0:
            return true
        case s[i].x0 > s[j].x0:
            return false
        case s[i].x1 > s[j].x1:
            return true
        default:
            return false
        }
    })
}

func f1(mySuperSlice []MySuperType) {
    sortByX0AscX1Desc(mySuperSlice)
    // do something with the sorted list
}
func f2(mySuperSlice []MySuperType) {
    sortBySomethingElse(mySuperSlice)
    // do something with the sorted list
}
func f3(mySuperSlice []MySuperType) {
    sortByX0AscX1Desc(mySuperSlice)
    // do something with the sorted list
}
 类似资料:
  • 问题内容: 我的孩子做了一项家庭作业,用Java编写二十一点。我为他提供了一些帮助,但大部分时间他都是自己完成的,实际上效果还不错。他甚至发现了我在计算手值时没有看到的错误。但是,他还没有解决一个难题,我能想到的每个解决方案都非常复杂,而且远远超出了他将能够利用其仍基本的Java技能轻松编写代码的范围。 王牌。实际上,不仅有一个Ace,还有四个Ace,您可能可以一手拿到所有四个Ace。当有一个或多

  • 问题内容: 一个激励人的例子: 实施各种调度“策略”,对“作业”列表进行排序。 一种非常简单的策略是首先执行最短的作业(不考虑其权重/优先级)。 嗯,这种策略只不过是对job.length进行排序,因此让我们使用sort包。定义一个自定义类型,并实现sort.Interface … 好了,现在回到我们的简单策略… 嗯… 问题答案: 首先, 即使您使用like ,也看不到任何定义 。 我认为您的意思

  • 现在我有了一个,它表示在特定时间板上当前的所有块。 我需要数一下一种类型有多少件,比如白车,黑皇后等,但正常的做法会变得太长,而且看起来很难看。我就是这么做的... 必须有一种更优雅的方法来实现这一点,它需要更少的代码行。我的意思是如果有超过6种类型的碎片和2种类型的颜色。我不能一直像这样给switch语句添加大小写,对吧?但我想不出怎样才能让它更优雅。

  • 本文向大家介绍数据结构中的各种排序方法小结(JS实现),包括了数据结构中的各种排序方法小结(JS实现)的使用技巧和注意事项,需要的朋友参考一下 新技术一直在不断变化,掌握一些基础是未来学习不断更新的技术的坚实基础。近来闲来无事,为了温习一下从前学的数据结构,将数据结构中的排序算法用JS实现了一遍,并在本文末尾处嵌入了DEMO。 简单排序 冒泡排序 冒泡排序是最简单排序算法,时间复杂度为n的平方,代

  • 本文向大家介绍Haskell优雅的镜片,包括了Haskell优雅的镜片的使用技巧和注意事项,需要的朋友参考一下 示例 除了makeLenses用于生成Lenses的标准功能外,Control.Lens.TH还提供该makeClassy功能。makeClassy具有相同的类型,并以与基本上相同的方式工作makeLenses,但有一个关键区别。除了生成标准的镜头和遍历之外,如果该类型没有参数,它还将创

  • 本文向大家介绍怎样写出优雅的HTML结构?相关面试题,主要包含被问及怎样写出优雅的HTML结构?时的应答技巧和注意事项,需要的朋友参考一下 请了解下雅虎军规