2015-11-08 11 views
-3

請幫助一個元編程配置,以便我可以添加名爲collectWithIndex和injectWithIndex的collection方法,它們以與每個WithIndex類似的方式工作,當然還包括collect和inject的基本功能。新方法將像每個WithIndex一樣接受兩個(三個映射)參數閉包。我希望能夠通過許多不同的腳本來利用這些方法。使用MetaProgramming添加collectWithIndex和injectWithIndex類似於每個WithIndex

使用案例:

List one = [1, 2, 3] 
    List two = [10, 20, 30] 
    assert [10, 40, 90] == one.collectWithIndex { value, index -> 
    value * two [index] 
    } 

一旦方法開發的,那麼如何將它提供給腳本?我懷疑是用特殊擴展信息創建一個jar文件,然後添加到classpath中。

提前

+0

SO是不是一個地方,你要求有人寫你的代碼。 您應該自己做__操作,如果您在此期間遇到特定問題 - 請提出__specific__問題,並在其中包含__您當前的進度___。這樣你就可以顯示你的報告和迄今取得的進展。 如果它是一個功能請求 - 在groovy [bug跟蹤器](https://issues.apache.org/jira/browse/GROOVY/)中提交它,或者在郵件列表中提出一個topick。請參閱[貢獻](http://groovy-lang.org/contribute.html)。 – Seagull

+0

我會發布代碼,如果我可以讓我的頭關閉和函數式編程。我不知道如何編寫一個名爲collectWithIndex的方法,該方法從一個列表或地圖對象中執行,並將閉包作爲參數。 – TeamDitto

+0

我已經添加了答案。當心,其他人會減去你,並忽略這個問題。而且,老實說,他們會是對的。 – Seagull

回答

0

我仍然相信很多感謝,這不是一個正確的SO問題,但我給你舉個例子,你怎麼可以充實元類爲你的多個腳本。

想法基於basescript,在其構造函數中向List的metaClass添加所需的方法。你必須自己實現收集邏輯,這很容易。您可以使用包裝

import org.codehaus.groovy.control.CompilerConfiguration 

class WithIndexInjector extends Script { 
    WithIndexInjector() { 
     println("Adding collectWithIndex to List") 
     List.metaClass.collectWithIndex { 
      int i = 0 
      def result = [] 
      for (o in delegate) // delegate is a ref holding initial list. 
       result << it(o, i++) // it is closure given to method 
      result 
     } 
    } 

    @Override Object run() { 
     return null 
    } 
} 

def configuration = new CompilerConfiguration() 
configuration.scriptBaseClass = WithIndexInjector.name 
new GroovyShell(configuration).evaluate(''' 
    println(['a', 'b'].collectWithIndex { it, id -> "[$id]:$it" }) 
''') 
// will print [[0]:a, [1]:b] 

如果你喜歡做的更多功能性的方式,而無需重複收集邏輯,你可以使用包裝代理關閉。我預計它會變慢,但也許這不是一筆交易。只需將collectWithIndex替換爲以下實施。

List.metaClass.collectWithIndex { 
    def wrappingProxyClosure = { Closure collectClosure, int startIndex = 0 -> 
     int i = startIndex 
     return { 
      collectClosure(it, i++) // here we keep hold on outer collectClosure and i, and use call former with one extra argument. "it" is list element, provided by default collect method. 
     } 
    } 
    delegate.collect(wrappingProxyClosure(it)) 
} 

offtopic:在SO社區當前的問題只會吸引優缺點,沒有答案。

+0

或者'''','b','c']。indexed()。collect {index,val - > [val,index]}' –

+0

或'['a','b',' c']。indexed()。inject([]){list,index,val - > list << [val,index]}' –

+0

@tim_yates酷,它是新的。我沒有注意到它被添加=)。 AFAICS這是一個轉換映射,因此有顯着的內存摺衷,轉換和訪問約2 * N。但它絕對很好。 – Seagull