[英]Sorting a list in Groovy in an unusual way
我有一个列表,让我们说[Cat, Dog, Cow, Horse]
,我希望按以下方式排序
Cat
在列表中,它应该首先出现 Cow
在名单上,它应该排在第二位 有什么建议如何在Groovy中完成?
蒂姆的回答非常聪明。 我个人更喜欢使用列表操作,因为它生成的代码稍微容易阅读。
def highPriority = [ 'Cat', 'Cow' ]
def list = [ 'Armadillo', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow', 'Cat' ]
def remainder = ( list - highPriority ).sort()
list.retainAll( highPriority )
list.sort{ highPriority.indexOf( it ) } + remainder
这会给你两次牛。 如果你不想重复,使用intersect非常简单。
def highPriority = [ 'Cat', 'Cow' ]
def list = [ 'Armadillo', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow', 'Cat' ]
list.intersect( highPriority ).sort{ highPriority.indexOf( it ) } + ( list - highPriority ).sort()
这应该这样做:
// Define our input list
def list = [ 'Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow' ]
// Define a closure that will do the sorting
def sorter = { String a, String b, List prefixes=[ 'Cat', 'Cow' ] ->
// Get the index into order for a and b
// if not found, set to being Integer.MAX_VALUE
def (aidx,bidx) = [a,b].collect { prefixes.indexOf it }.collect {
it == -1 ? Integer.MAX_VALUE : it
}
// Compare the two indexes.
// If they are the same, compare alphabetically
aidx <=> bidx ?: a <=> b
}
// Create a new list by sorting using our closure
def sorted = list.sort false, sorter
// Print it out
println sorted
打印:
[Cat, Cow, Cow, Armadillo, Dog, Horse, Zebra]
我评论它试图解释它所采取的每一步。 通过在sorter
闭包上添加默认前缀项作为可选参数,这意味着我们可以执行以下操作来更改默认值:
// Use Dog, Zebra, Cow as our prefix items
def dzc = list.sort false, sorter.rcurry( [ 'Dog', 'Zebra', 'Cow' ] )
println dzc
然后打印列表排序为:
[Dog, Zebra, Cow, Cow, Armadillo, Cat, Horse]
这是另一种让我感觉更简单的选择:
// smaller values get sorted first
def priority(animal) {
animal in ['Cat', 'Cow'] ? 0 : 1
}
def list = [ 'Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow' ]
def sorted = list.sort{ a, b -> priority(a) <=> priority(b) ?: a <=> b }
assert sorted == ['Cat', 'Cow', 'Cow', 'Armadillo', 'Dog', 'Horse', 'Zebra']
如果您没有重复的元素,可以尝试这样做:
def highPriority = [ 'Cat', 'Cow' ]
def list = [ 'Armadillo', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cat' ]
highPriority + list.minus(highPriority).sort()
这个问题已经很老了,但今天我发现Groovy有一个相当无证的OrderBy
比较器,在这种情况下可以使用:
def highPriority = ['Cow', 'Cat']
def list = ['Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow']
def sorted = list.sort new OrderBy([{ -highPriority.indexOf(it) }, { it }])
assert sorted == ['Cat', 'Cow', 'Cow', 'Armadillo', 'Dog', 'Horse', 'Zebra']
OrderBy
比较器首先使用取消的highPriority
列表中的索引来比较动物(因此,不高优先级的动物(即索引-1)被移动到列表的后面),如果索引相等,则将它们与身份函数{it}
,作为动物是字符串,按字母顺序对它们进行排序。
灵感来自tomas的回答 :
def highPriority = [ 'Cat', 'Cow' ]
def list = [ 'Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow' ]
// Group animals by priority.
def groups = list.groupBy { it in highPriority ? it : 'rest' }
// High priority animals are sorted by priority and the rest alphabetically.
def sorted = highPriority.collectMany { groups[it] } + groups['rest'].sort()
assert sorted == ['Cat', 'Cow', 'Cow', 'Armadillo', 'Dog', 'Horse', 'Zebra']
groups
变量类似于[rest:[Armadillo, Dog, Zebra, Horse], Cat:[Cat], Cow:[Cow, Cow]]
。
另一个可能不那么强大的解决方案可能是:
def sorted = list.sort(false) {
def priority = highPriority.indexOf(it)
if (priority == -1) priority = highPriority.size()
// Sort first by priority and then by the value itself
"$priority$it"
}
它不像"2Armadillo"
, "0Cat"
等字符串那样排序,如果你有9个或更多的高优先级动物(因为"10Alpaca" < "9Eel"
,它将"10Alpaca" < "9Eel"
。如果Groovy提供了某种类似的元组类型,比如Python的元组 ,那么很酷,所以不是将"$priority$it"
作为可比较的键返回(priority, it)
可以返回元组(priority, it)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.