在Go语言中进行排序

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

Sorting in golang

问题

我正在使用Go语言创建一个请假申请。我的结构如下:

type Leave struct {
    Leaveid     int
    Name        string
    EmployeeId  string
    Applieddate time.Time
    Leavestatus string
}

请假状态有多种,包括Processing、Approved、Denied、HRApproved、HrDenied和HrProcessing。通常情况下,请假排序应该基于申请日期。我希望能够首先显示Processing和HRProcessing状态,然后显示其他状态类型。

你想要的结果类似于:

[
  {
    "Leaveid": 4,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T08:59:02.870882+08:00",
    "Leavestatus": "HRProcessing"
  },
  {
    "Leaveid": 1,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T07:30:01.679636+08:00",
    "Leavestatus": "Processing"
  },
  {
    "Leaveid": 3,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T07:00:02.870882+08:00",
    "Leavestatus": "HRProcessing"
  },
  {
    "Leaveid": 5,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T10:00:11.139189+08:00",
    "Leavestatus": "Approved"
  },
  {
    "Leaveid": 2,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T07:58:41.837666+08:00",
    "Leavestatus": "HRApproved"
  }
]

更新:这是我使用sort包完成的代码:

type leaveDetails []Leave

func (sortleave leaveDetails) Len() int {
    return len(sortleave)
}

func (sortleave leaveDetails) Less(i, j int) bool {
    if sortleave[i].Applieddate.After(sortleave[j].Applieddate) {
        return true
    }
    if sortleave[i].Applieddate.Before(sortleave[j].Applieddate) {
        return false
    }
    return sortleave[i].Leavestatus > sortleave[j].Leavestatus
}

func (sortleave leaveDetails) Swap(i, j int) {
    sortleave[i], sortleave[j] = sortleave[j], sortleave[i]
}

输出结果为:

[
  {
    "Leaveid": 2,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T08:59:45.139189+08:00",
    "Leavestatus": "HRProcessing"
  },
  {
    "Leaveid": 4,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T08:59:02.870882+08:00",
    "Leavestatus": "HRApproved"
  },
  {
    "Leaveid": 3,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-02T08:58:41.837666+08:00",
    "Leavestatus": "Processing"
  },
  {
    "Leaveid": 1,
    "Name": "rajesh",
    "EmployeeId": "rajesh",
    "Applieddate": "2016-12-01T18:10:01.679636+08:00",
    "Leavestatus": "Processing"
  }
]

在这个结果中,Processing状态被放在了后面,而HRApproved状态被放在了前面。但这不是你想要的结果。请帮助我解决这个问题。谢谢!

英文:

I am creating a leave application using go lang.<be>My struct is as follows

Leave struct {
		Leaveid     int
		Name        string
		EmployeeId  string
		Applieddate time.Time
		Leavestatus string
	}

The Leave status varies between Processing ,Approved ,Denied, HRApproved, HrDenied, HrProcessing. <br>By general the leave sort order must be based on applied date.<br>I must be able to show the Processing and HRProcessing first and other status types later.

I want something like this

        [
          {
            &quot;Leaveid&quot;: 4,
            &quot;Name&quot;: &quot;rajesh&quot;,
            &quot;EmployeeId&quot;: &quot;rajesh&quot;,
            &quot;Applieddate&quot;: &quot;2016-12-02T08:59:02.870882+08:00&quot;,
            &quot;Leavestatus&quot;: &quot;HRProcessing&quot;
          },
          {
            &quot;Leaveid&quot;: 1,
            &quot;Name&quot;: &quot;rajesh&quot;,
            &quot;EmployeeId&quot;: &quot;rajesh&quot;,
            &quot;Applieddate&quot;: &quot;2016-12-02T07:30:01.679636+08:00&quot;,
            &quot;Leavestatus&quot;: &quot;Processing&quot;
          },
{
            &quot;Leaveid&quot;: 3,
            &quot;Name&quot;: &quot;rajesh&quot;,
            &quot;EmployeeId&quot;: &quot;rajesh&quot;,
            &quot;Applieddate&quot;: &quot;2016-12-02T07:00:02.870882+08:00&quot;,
            &quot;Leavestatus&quot;: &quot;HRProcessing&quot;
          },
         {
            &quot;Leaveid&quot;: 5,
            &quot;Name&quot;: &quot;rajesh&quot;,
            &quot;EmployeeId&quot;: &quot;rajesh&quot;,
            &quot;Applieddate&quot;: &quot;2016-12-02T10:00:11.139189+08:00&quot;,
            &quot;Leavestatus&quot;: &quot;Approved&quot;
          },
          {
            &quot;Leaveid&quot;: 2,
            &quot;Name&quot;: &quot;rajesh&quot;,
            &quot;EmployeeId&quot;: &quot;rajesh&quot;,
            &quot;Applieddate&quot;: &quot;2016-12-02T07:58:41.837666+08:00&quot;,
            &quot;Leavestatus&quot;: &quot;HRApproved&quot;
          },
     
        ]

> Update:This is what i have done using sort package

func (sortleave leaveDetails) Len() int {
	return len(sortleave)
}
func (sortleave leaveDetails) Less(i, j int) bool {
	if sortleave[i].Applieddate.After(sortleave[j].Applieddate) {
		return true
	}
	if sortleave[i].Applieddate.Before(sortleave[j].Applieddate) {
		return false
	}
	return sortleave[i].Leavestatus &gt; sortleave[j].Leavestatus
}
func (sortleave leaveDetails) Swap(i, j int) {
	sortleave[i], sortleave[j] = sortleave[j], sortleave[i]
}

Output:

[
  {
    &quot;Leaveid&quot;: 2,
    &quot;Name&quot;: &quot;rajesh&quot;,
    &quot;EmployeeId&quot;: &quot;rajesh&quot;,
    &quot;Applieddate&quot;: &quot;2016-12-02T08:59:45.139189+08:00&quot;,
    &quot;Leavestatus&quot;: &quot;HRProcessing&quot;
  },
  {
    &quot;Leaveid&quot;: 4,
    &quot;Name&quot;: &quot;rajesh&quot;,
    &quot;EmployeeId&quot;: &quot;rajesh&quot;,
    &quot;Applieddate&quot;: &quot;2016-12-02T08:59:02.870882+08:00&quot;,
    &quot;Leavestatus&quot;: &quot;HRApproved&quot;
  },
  {
    &quot;Leaveid&quot;: 3,
    &quot;Name&quot;: &quot;rajesh&quot;,
    &quot;EmployeeId&quot;: &quot;rajesh&quot;,
    &quot;Applieddate&quot;: &quot;2016-12-02T08:58:41.837666+08:00&quot;,
    &quot;Leavestatus&quot;: &quot;Processing&quot;
  },
  {
    &quot;Leaveid&quot;: 1,
    &quot;Name&quot;: &quot;rajesh&quot;,
    &quot;EmployeeId&quot;: &quot;rajesh&quot;,
    &quot;Applieddate&quot;: &quot;2016-12-01T18:10:01.679636+08:00&quot;,
    &quot;Leavestatus&quot;: &quot;Processing&quot;
  }
]

Here Processing goes down and HRApproved goes up.But this is not what i wanted.Please help me to solve this problem.Thanks

答案1

得分: 1

你需要首先按照Leavestatus进行排序,然后按照applieddate进行排序。但是Leavestatus是一组枚举值,而不是按字母顺序排序的,所以你需要对状态进行分类,看它们是否相同,如果相同,则按日期排序,否则按状态排序。类似这样的代码:

func (d leaveDetails) Less(i, j int) bool {
    status := func(l Leave) int {
        if l.Leavestatus == "Processing" || l.Leavestatus == "HRProcessing" {
            return 1
        }
        return 2
    }
    a := status(d[i])
    b := status(d[j])
    if a == b {
        return d[i].Applieddate.After(d[j].Applieddate)
    }
    return a < b
}
英文:

You need to sort by Leavestatus first,then applieddate, but leavestatus is a set of enums rather than being alpha sorted, so you'll want to catogorize the status, see if they're they same if so, sort by date, otherwise sort by the status. something like

func (d leaveDetails) Less(i, j int) bool {
    status := func(l Leave) int {
        if l.Leavestatus == &quot;Processing&quot; || l.Leavestatus == &quot;HRProcessing&quot; {
            return 1
        }
        return 2
    }
    a := status(d[i])
    b := status(d[j])
    if a == b {
        return d[i].Applieddate.After(d[j].Applieddate)
    }
    return a&lt;b
}

答案2

得分: 0

Leavestatus定义为string似乎效率不高,因为你需要进行字符串比较,并且复制结构体时需要复制Leavestatus,即使它只是一个类似于"enum"的类型。这也使得引入基于拼写错误的错误更容易,因为编译器无法检查你是否正确输入了字符串。

我会为Leavestatus创建一个基于整数的类型,例如LeaveStatus

type LeaveStatus int

const (
    _ = iota
    Processing
    HRProcessing
    HRApproved
)

然后你可以在该类型上定义String()方法:

func (s LeaveStatus) String() string {
    switch(s) {
        case Processing:
            return "Processing"
        case HRProcessing:
            return "HRProcessing"
        case Approved:
            return "Approved"
        default:
            panic("O_O")
    }
}

由于LeaveStatus现在是基于数字的类型,你可以在Less()实现中使用<>运算符来比较字段。

英文:

Defining Leavestatus as a string seems pretty inefficient since you'd need to do string comparison and copying the struct involves copying the Leavestatus even though it's just a "enum"-like type. This also makes it easier to introduce typo-based bugs since compiler can't check if you typed strings right.

I would make a int based type for Leavestatus, e.g. LeaveStatus

type LeaveStatus int

const (
    _ = iota
    Processing
    HRProcessing
    HRApproved
)

Then you can have String() method on the type:

func (s LeaveStatus) String() string {
    switch(s) {
        case Processing:
            return &quot;Processing&quot;
        case HRProcessing:
            return &quot;HRProcessing&quot;
        case Approved:
            return &quot;Approved&quot;
        default:
            panic(&quot;O_O&quot;)
    }
}

Since LeaveStatus is a number-based type now, you can just compare the field using &lt; and &gt; operators in your Less() implementation.

huangapple
  • 本文由 发表于 2016年12月2日 10:03:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/40923603.html
匿名

发表评论

匿名网友

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

确定