2011-09-23 85 views
0

有沒有更好的方法來找到更小的標記最接近的對象?Groovy基於成員屬性查找最大匹配列表成員的方法

class Prop implements Comparable { 
    BigDecimal marker 
    String value 

    int compareTo(other) { 
    return marker <=> other.marker 
    } 

} 

def props = [new Prop(marker: 0G, value: "1st"), 
new Prop(marker: 20G, value: "2nd"), 
new Prop(marker: 30G, value: "3rd"), 
new Prop(marker: 40G, value: "4th"), 
new Prop(marker: 50G, value: "5th"), 
new Prop(marker: 100G, value: "6th"), 
new Prop(marker: 1000G, value: "7th")] 

def whereAmI = 44G 

def here = props.findAll{it.marker <= whereAmI}.max() 

回答

2

編輯:更新返回正確的對象類型和空值。

假設順序是沒有保證的,你可以使用the inject method

// Inject null, so if nothing is lower than max, this returns null 
def here = props.inject(null){ max, it -> 
    (it.marker <= whereAmI && (!max || it > max)) ? it : max 
} 

如果列表中總是排序,然後只需使用:

// Inject null, so if nothing is lower than max, this returns null 
def here = props.inject(null){ max, it -> 
    (it.marker <= whereAmI) ? it : max 
} 

這樣做的好處是你唯一的循環超過設置一次,並且您不會創建較小值的額外臨時List

現在,根據您的列表大小,參數可能是您的原始示例更容易閱讀,並且更清晰。代碼清晰可以勝過性能。

(注:inject是Groovy的版本的reduce or fold

+0

輕微這裏的問題是,你是返回一個Double而不是道具 – Micor

+0

這將是比較容易修改。對不起,我錯過了。基本上,用列表中的第一項替換初始注入,並在'max.marker'上進行比較。我會更新這個例子。 – OverZealous

+0

好吧,我做了一點不同,並注入空,所以你可以知道你是否在列表的開始。希望有幫助。 – OverZealous

0

下面就以過激的注射液的選擇,如果道具列表是按標記分類的作品。創建上列出了takeWhile方法,然後拿比whereAmI少最後一個:

List.metaClass.takeWhile = { closure -> 
    def iter = delegate.iterator() 
    int i = 0 
    def n = iter.next() 
    while(closure.call(n)) { 
     i++ 
     if (iter.hasNext()) 
      n = iter.next() 
     else 
      break 
    } 
    return delegate[0..<i] 
} 

props.takeWhile { it.marker < whereAmI }[-1]   // exception if nothing matches 
props.takeWhile { it.marker < whereAmI }.reverse()[0] // null if nothing matches 
0

什麼更好的方式來做到這一點是取決於你認爲是更好的。

對於代碼可讀性,我認爲您最初提出的解決方案非常好。

過度的solution migth會更快,但正如他所說,它不是可讀的。事實上,如果性能對於代碼非常重要,則應該對其進行配置以查看它是否真的更快。

如果創建props列表一次(或幾次),但here值計算很多次,你migth考慮排序props並用二進制搜索尋找whereAmI。這將花費log(n)時間(n的大小爲props)而不是線性時間。

// Make whereAmI a Prop to avoid defining a Comparator 
def whereAmI = new Prop(marker: 44G, value: '') 
def i = Collections.binarySearch(props, whereAmI) 
def here = props[i >= 0 ? i : -i - 2] 

whereAmI時不處於propsbynarySearch返回一個的負加上其中whereAmI應,因此看似神奇-1 -2那裏索引。

警告:如果props中沒有元素小於whereAmI,則此操作將不起作用。如果這是可能的情況,你應該要求i == -1。在這種情況下,分配給nullhere原代碼:

def here = i == -1 ? null : props[i >= 0 ? i : -i - 2]