有指数的.collect
吗?我想做这样的事情:
def myList = [
[position: 0, name: 'Bob'],
[position: 0, name: 'John'],
[position: 0, name: 'Alex'],
]
myList.collect { index ->
it.position = index
}
(即我想将position
设置为一个值,该值将指示列表中的顺序)
从Groovy 2.4.0开始,有一个withIndex()
方法被添加到java.lang.Iterable
。
因此,在功能性方面(没有副作用,不可变),它看起来像
def myList = [
[position: 0, name: 'Bob'],
[position: 0, name: 'John'],
[position: 0, name: 'Alex'],
]
def result = myList.withIndex().collect { element, index ->
[position: index, name: element["name"]]
}
稍微更加时髦的collectWithIndex版本:
List.metaClass.collectWithIndex = {body->
def i=0
delegate.collect { body(it, i++) }
}
甚至
List.metaClass.collectWithIndex = {body->
[delegate, 0..<delegate.size()].transpose().collect(body)
}
eachWithIndex
可能会更好地工作:
myList.eachWithIndex { it, index ->
it.position = index
}
使用collectX
似乎并不是必需的,因为您只是修改集合而不是将其中的特定部分返回到新集合中。
这应该完全符合你的要求
List.metaClass.collectWithIndex = {cls ->
def i = 0;
def arr = [];
delegate.each{ obj ->
arr << cls(obj,i++)
}
return arr
}
def myCol = [
[position: 0, name: 'Bob'],
[position: 0, name: 'John'],
[position: 0, name: 'Alex'],
]
def myCol2 = myCol.collectWithIndex{x,t ->
x.position = t
return x
}
println myCol2
=> [[position:0, name:Bob], [position:1, name:John], [position:2, name:Alex]]
在不添加任何扩展方法的情况下,您可以以非常简单的方式执行此操作:
def myList = [1, 2, 3]
def index = 0
def myOtherList = myList.collect {
index++
}
尽管如此,这种方法自然存在肯定是有用的。
就像dstarh所说的那样,除非你正在寻找一种非破坏性的方法来返回一个填充了你的索引的新地图,Rob Hruska的答案就是你正在寻找的。
dstarh的答案为您提供collectWithIndex
的非破坏性版本,但也处理实际的结果集合。
我通常发现最好将这样繁重的工作委托给接收对象,以便与多态的collect
实现很好地配合,即,如果特定的类以不同的方式实现collect
(而不仅仅是将结果放入数组中),让collectWithIndex
委托给它将确保统一的行为。以下是代码的外观:
@Category(List)
class Enumerator {
def collectWithIndex(Closure closure) {
def index = 0
this.collect { closure.call(it, index++) }
}
}
use(Enumerator) {
['foo', 'bar', 'boo', 'baz'].collectWithIndex { e, i ->
[index: i, element: e]
}
}
有关this gist和eachWithIndex
的示例,请参阅collectWithIndex
。
此外,就像您对问题状态的评论一样,我们所描述的功能有两个Jira问题 - GROOVY-2383&GROOVY-3797