【问题标题】:How can a Groovy method return multiple times?Groovy 方法如何多次返回?
【发布时间】:2015-09-18 12:45:05
【问题描述】:

我正在尝试通过以下代码从排序地图中获取前 K 个元素:

//return top rank k elements
public static LinkedHashMap<String,Double> getTopRank(int i){
    //store top k elements
    LinkedHashMap<String, Double> result=new LinkedHashMap<>();
    int count=0;
    //use the static rankMap in the class
    rankMap.each {key,value->
        result.put(key, value);
        count++;
        if(count>=i){
            println "Time to return"
            return result;
        }
    }
    //in case the loop does not work
    return result;
}

我期望的是,当结果 Map 已经有 i 个元素的大小时,该方法将返回,给我一个 i-size 排序的地图。请注意,rankMap 按我想要的特定顺序存储元素,并且它的大小远大于我传递给方法的 int i。 我通过

调用该方法
LinkedHashMap<String,Double> content=getTopRank(outputSize);

但没想到最终内容的大小是rankMap而不是i!在控制台中,我看到了数百行 Time to return 行。 return result 行一次又一次地执行,直到到达rankMap 的末尾。 我很确定getTopRank(outputSize) 这行没有循环。然后我觉得奇怪为什么这个方法可以多次返回而没有结束。是因为我在闭包中放入了return 语句吗? 请告知或告诉我这在 Groovy 中是如何实现的。更进一步,我怎样才能从排序的地图中只获取前 k 个元素?

【问题讨论】:

  • 使用 collect 而不是 each 你可以实现你的目标
  • 收集没有多大帮助
  • 有些语言有“yield”的概念,Groovy 没有。存在一些 SO 讨论,(免责声明不能说质量)stackoverflow.com/questions/30743472/…

标签: groovy


【解决方案1】:

您误解了 Groovy 的关键概念。

在到达结束之前完成each() 执行的唯一方法是抛出异常。如果您想有条件地退出循环,请使用标准循环类型,例如 forwhile

int count=0
def result = [:]
for( def e in rankMap ){
  count++
  result[ e.key ] = e.value
  if( i <= count ) return result
}

【讨论】:

  • myMap.take(i) 更像 Groovy
  • 当然。问题是关于关闭时的returning,这就是为什么我把for()
  • 你对 each() 的解释是正确的。您的解决方案也是该示例的工作版本。但很明显 OrlandoL 来自 Java 背景,没有太多 Groovy 经验(或参考 Groovy 文档)。我觉得推动正确的 Groovy 方法比用他们已经熟悉的语言修复它更有益。您的解决方案不鼓励阅读任何文档,这确实是问题归结为。
  • 好吧,我的解决方案确实鼓励阅读文档,因为不知道非常基本的 groovy 收集方法是如何工作的,你就无法真正有效地进行
  • 顺便说一句,map.take i 更时髦 ;)
【解决方案2】:

方法本身没有返回。 each 是一个接收闭包的方法。闭包有自己的返回上下文,它与调用它们的方法无关,因此循环不会中断。

我想建议从地图的entrySet 中获取一个范围并收集结果条目:

def getTopRank(int i) {
    rankMap
        .entrySet()
        .toList()[0..<i]
        .collectEntries()
}

rankMap = [
    'Beatles'        : 'The White Album',
    'Pink Floyd'     : 'The Dark Side of the Moon',
    'Rolling Stones' : 'Sticky Fingers',
    'The Doors'      : 'Morrison Hotel',
    'Bob Dylan'      : 'Bob Dylan'
]


assert getTopRank(2) == [
    'Beatles'    : 'The White Album',
    'Pink Floyd' : 'The Dark Side of the Moon']

assert getTopRank(4) == [
    'Beatles'        : 'The White Album',
    'Pink Floyd'     : 'The Dark Side of the Moon',
    'Rolling Stones' : 'Sticky Fingers',
    'The Doors'      : 'Morrison Hotel',]

【讨论】:

    【解决方案3】:
    public static LinkedHashMap<String,Double> getTopRank(int i){
        rankMap.take(i)
    }
    

    http://www.groovy-lang.org/gdk.html
    http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Map.html#take(int)

    【讨论】:

    • 请注意 take() 自 groovy 1.8.1 以来可用,这在老式设置中可能是一个问题。另外,这里有个问题,map 应该是LinkedHashMap 的一个实例,否则你会得到随机结果
    猜你喜欢
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    • 2015-08-23
    • 2019-08-21
    • 1970-01-01
    相关资源
    最近更新 更多