Grails 查找(闭包)并针对该值执行

Grails 查找(闭包)并针对该值执行,grails,groovy,Grails,Groovy,实际上,我的问题是“下面的代码示例可以更小吗?基本上,代码示例设计为首先查看对象列表,找到最细粒度的对象(在本例中是分支),然后根据找到的对象向后查询 1-如果找到分支,则返回该分支的findAllBy 2-如果找到部门,则返回该部门的findAllBy 3-如果找到组织,则返回该组织的findAllBy 目标是找到最细粒度的对象(这就是为什么顺序很重要),但我是否需要有两个单独的块(一个用于定义对象,另一个用于检查对象是否存在)?或者可以将这两个执行合并为一个命令 def resp def s

实际上,我的问题是“下面的代码示例可以更小吗?基本上,代码示例设计为首先查看对象列表,找到最细粒度的对象(在本例中是分支),然后根据找到的对象向后查询

1-如果找到分支,则返回该分支的findAllBy

2-如果找到部门,则返回该部门的findAllBy

3-如果找到组织,则返回该组织的findAllBy

目标是找到最细粒度的对象(这就是为什么顺序很重要),但我是否需要有两个单独的块(一个用于定义对象,另一个用于检查对象是否存在)?或者可以将这两个执行合并为一个命令

def resp
def srt = [sort:"name", order:"asc"]

def branch = listObjects.find{it instanceof Branch} 
def department = listObjects.find{it instanceof Department}
def organization = listObjects.find{it instanceof Organization}

resp = !resp && branch ? Employees.findAllByBranch(branch,srt) : resp
resp = !resp && department ? Employees.findAllByDepartment(department,srt) : resp
resp = !resp && organization ? Employees.findAllByOrganization(organization,srt) : resp

return resp
我的想法大致如下:

def resp
resp = Employees.findAllByBranch(listObjects.find{it instanceof Branch})
resp = !resp ? Employees.findAllByDepartment(listObjects.find{it instanceof Department}) : resp
resp = !resp ? Employees.findAllByOrganization(listObjects.find{it instanceof Organization}) : resp
但我相信这会引发异常,因为这些对象可能为null for-in循环更有效,因为您希望在第一个非空结果上中断处理(即,在Groovy中,我们不能用“return”或“break”中断闭包迭代)

原件

List results = [Branch,Department,Organization].collect{clazz->  
    Employees."findAllBy${clazz.name}"(listObjects?.find{it instanceof $clazz})  
}
享受Groovy;-)

我想,但是您希望使用find,而不是collect(正如他所说的,您无法摆脱collect),因为它会停止运行它得到的第一个有效结果:

List results = [Branch,Department,Organization].find { clazz->  
    Employees."findAllBy${clazz.name}"(listObjects?.find{it instanceof clazz})  
}

您可以使用
findResult
将其缩短一点,而不是使用需要定义外部变量的for-in循环:

def listObjects // = some predetermined list that you've apparently created
def srt = [sort:"name", order:"asc"]

def result = [Branch, Department, Organization].findResult { clazz -> 
    listObjects?.find { it.class.isAssignableFrom(clazz) }?.with { foundObj ->
        Employees."findAllBy${clazz.name}"(foundObj, srt)
    }
}
findResult
类似于
find
,但它从第一个非空项而不是项本身返回结果。它避免了在循环之外需要单独的集合变量

编辑:我之前所做的与我认为您正在寻找的行为不太匹配(我认为其他答案也不匹配,但我可能会误解)。在进行findAllBy之前,您必须确保列表中有某些内容,否则您可以撤回您不需要的空项

在实际的生产代码中,我实际上会做一些不同的事情。我会利用JVM类型的系统,只需在
listObjects
中旋转一次,然后在找到第一个分支/部门/组织时短路,如下所示:

def listObjects
def sort = [sort:"name", order:"asc"]

def result = listObjects?.findResult { findEmployeesFor(it, sort) }

...  // then have these methods to actually exercise the type specific findEmployeesFor

def findEmployeesFor(Branch branch, sort) { Employees.findAllByBranch(branch, sort) }
def findEmployeesFor(Department department, sort { Employees.findAllByDepartment(department, sort)}
def findEmployeesFor(Organization organization, sort { Employees.findAllByOrganization(organization, sort)}
def findEmployeesFor(Object obj, sort) { return null } // if listObjects can hold non/branch/department/organization objects

我认为这段代码实际上更清晰,它减少了我们在列表上的迭代次数和我们需要进行的反射调用的次数。

我认为我必须做一个小小的更改:find{it instanceof$clazz})抛出了一个编译错误,所以我将其更改为find{it.class.isAssignableFrom(clazz)}编译结束了,我还不能完全测试这是否是正确的方法。对,请查看旧的Nabble Grails用户论坛,可能有一种“Grails方法”可以在动态查找器上获取返回类型:恐怕是查找{}将只返回三个类中的一个,而不是我们想要的闭包结果。你是对的…对此很抱歉…Ted给出了答案:-)很好的劫持;-)首先你“将事情缩短一点(与我在解决方案中的完全有效相比)”,然后提供一个几乎与OP一样详细的结果,哈哈。问题是“下面的代码示例可以更小吗?很明显,它可以。因为在第一个非null返回的情况下,@tim_yates的解决方案更符合“精神”“根据OP的要求;即简洁。为我的语气道歉,只是对我的回答被打断感到恼火,啊哈,新的&学会了所谓的诀窍;--)对不起,你说得对,那有点像劫机。我的原始版本较短,但如果在所有情况下都执行的话(其他的实现也一样),它实际上不起作用。在您编辑的方法中,以及tim_yate的回答中,如果
listObjects?.find…
返回空值,我相信findAllBy将返回所有分支/部门/组织为空的员工(否则它会爆炸,忘记哪个)。这不是OP想要的(除非在他的系统中,所有员工都必须有一个分支机构、一个部门和一个组织。这样就可以了,但如果不知道更多,就很难知道了。感谢你的诚实;--)你有很高的代表性,特别是在Groovy land,所以我会在适当的时候推迟。正如您所说,OP可能需要考虑listObject空值并影响给定的findBy*。Short&sweet不错,但必须涵盖所有基础。干杯……把所有这些都标记为有效的答案是很好的——我的问题没有明确,这三个回答导致了从各个方面思考这个问题的一些好方法(“我如何缩短这个时间”以及“最好的方式是什么”)。谢谢大家的回答。
def listObjects
def sort = [sort:"name", order:"asc"]

def result = listObjects?.findResult { findEmployeesFor(it, sort) }

...  // then have these methods to actually exercise the type specific findEmployeesFor

def findEmployeesFor(Branch branch, sort) { Employees.findAllByBranch(branch, sort) }
def findEmployeesFor(Department department, sort { Employees.findAllByDepartment(department, sort)}
def findEmployeesFor(Organization organization, sort { Employees.findAllByOrganization(organization, sort)}
def findEmployeesFor(Object obj, sort) { return null } // if listObjects can hold non/branch/department/organization objects