查找两个列表之间的公共元素时发生堆栈溢出错误

时间:2012-07-26 11:25:53

标签: groovy stack-overflow

我有这段代码:

def input1 = ['a','b','e','r','t']
input2 = ['v','n','m','y']
ans = []

def common(def element,def i) {
  if (element == input2[i]) {
    ans << element
    return
  } else {
    common(element,++i)
  }
}  

for (i=0;i<input1.size();i++) {
  common(input1[i],0)
}

正在生成Stack Overflow错误。为什么会这样?

编辑:

我正在尝试创建自己的方法来查找两个列表之间的共同元素。

2 个答案:

答案 0 :(得分:2)

您永远不会检查i是否大于input2的长度,而在Groovy中,超出List的长度会返回null

所以在第一个元素上,它将继续循环

if (element == input2[i]) {

不断增加i的值,每次调用common函数,因为它永远不会匹配a

猜测你想要做什么,这一切都可以重写为:

def input1 = ['a','b','e','r','t']
def input2 = ['v','n','m','y']
def ans = input1.intersect( input2 )

但很难确定你想要什么,而且你没有明确说出来。

修改

避免Stack Overflows的一种深度递归方法是使用Groovy's trampoline method

def common
common = { Object element, Collection list ->
  if( list.size() == 0 ) {                     // element not found.  Return null
    null
  }
  else if( list.head() == element ) {          // element found.  Return it
    element
  }
  else {
    common.trampoline( element, list.tail() )  // Trampoline down the list and check again
  }
}
common = common.trampoline()

def elements = ['a','b','e','v','r','t'].collect { // For each element in this list
                 common( it, ['v','n','m','y'] )   // Find if it's in our other list
               }.findAll()                         // And remove the nulls

assert elements == [ 'v' ]

但在这种情况下我仍然使用intersect,上面只是为了展示Groovy的一种方法,你可以避免太深的递归......

答案 1 :(得分:0)

问题是你的代码在到达数组input2的末尾时不会停止。如果element不在input2中,那么它将继续永远进行递归调用 common(element,++ i),这会导致堆栈溢出错误。