簡體   English   中英

以不尋常的方式在Groovy中對列表進行排序

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM