2016-10-18 13 views
0

"宝を見つけたら、掘りなさい!"機能的なGroovyの短絡?

私はGroovyでより機能的なプログラミングを使いたいと思っています。次の方法を書き直すと良い訓練になると思います。 Groovyは、より機能的な機能に短絡するように見えないので、見た目よりも難しいです。それは、完全修飾ファイル名のリストをスキャンし、最短のユニークな形を返し

fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e'] 
String shortestUniqueName(String nameToShorten) { 
    def currentLevel = 1 
    String shortName = '' 
    def separator = '/' 
    while (fullyQualifiedNames.findAll { fqName -> 
     shortName = nameToShorten.tokenize(separator)[-currentLevel..-1].join(separator) 
     fqName.endsWith(shortName) 
    }.size() > 1) { 

     ++currentLevel 

    } 

    return shortName 
} 

println shortestUniqueName('a/b/c/d/e') 

Result: c/d/e 

はここで仕事をすることが不可欠の機能です。潜在的に何百もの完全修飾名があります。

メソッドが1つの一致で短い名前を見つけるとすぐに、その短い名前が正しい答えであり、反復が停止する可能性があります。残りの名前をスキャンしたり、高価なリスト検索をする必要はありません。

しかし、Groovyでより多くの機能フローに目を向け、どちらreturnbreakは、反復のあなたをドロップすることができます。

return単に全体ではなく.eachから、現在の反復から返すので、それは短期はありません回路。

breakはループ外では許可されず、.each {}.eachWithIndex {}はループ構造とはみなされません。

私のプログラムロジックでは、リストのすべての要素をスキャンする必要があるため、.findAll()ではなく、.find()を使用することはできません。

try..catchブロックを使用しないような理由がたくさんありますが、私が読んだ最高のfrom here次のとおりです。

例外は、基本的には後者のすべて 結果を伴う非ローカルのgoto文です。フロー制御の例外を使用する は、最小の驚きの原則に違反し、プログラムを読みにくくするようにします。 (最初にプログラマー向けに作成されたプログラムです)。

.eachの新しいフレーバに基づく解決方法を含むhereがあります。 (進行中の)これは私がこれまでに見つけた解決策に最も近いですが、私は私のユースケースのため.eachWithIndex()を使用する必要が

ここで短絡機能液で自分が悪いの試みです:

fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e'] 
def shortestUniqueName(String nameToShorten) { 
    def found = '' 
    def final separator = '/' 
    def nameComponents = nameToShorten.tokenize(separator).reverse() 
    nameComponents.eachWithIndex { String _, int i -> 
     if (!found) { 
      def candidate = nameComponents[0..i].reverse().join(separator) 
      def matches = fullyQualifiedNames.findAll { String fqName -> 
       fqName.endsWith candidate 
      } 
      if (matches.size() == 1) { 
       found = candidate 
      } 
     } 
    } 
    return found 
} 

println shortestUniqueName('a/b/c/d/e') 

Result: c/d/e 

私が考えていないGroovyで短絡するより慣用的な方法がある場合は、私を撃墜してください。ありがとうございました!

+0

可能な重複[Groovyのクロージャから1つのリターンとは、その実行を停止しない方法は?] (http://stackoverflow.com/questions/765605/how-does-one-return-from-a-groovy-closure-and-stop-its-execution) –

答えて

0

ありクリーナーを探して(そして読みやすい)ソリューション、おそらくですが、あなたはこの種のものを行うことができます。

String shortestUniqueName(String nameToShorten) { 
    // Split the name to shorten, and make a list of all sequential combinations of elements 
    nameToShorten.split('/').reverse().inject([]) { agg, l -> 
     if(agg) agg + [agg[-1] + l] else agg << [l] 
    } 
    // Starting with the smallest element 
    .find { elements -> 
     fullyQualifiedNames.findAll { name -> 
      name.endsWith(elements.reverse().join('/')) 
     }.size() == 1 
    } 
    ?.reverse() 
    ?.join('/') 
    ?: '' 
}