나는 이것에 대해 약간의 정렬을 원합니다.
Map rowToMap(row) {
def rowMap = [:];
row.columns.each{ rowMap[it.name] = it.val }
return rowMap;
}
GDK 물건이있는 방식을 고려하면 다음과 같은 작업을 수행 할 수있을 것으로 기대합니다.
Map rowToMap(row) {
row.columns.collectMap{ [it.name,it.val] }
}
하지만 문서에서 아무것도 보지 못했습니다 … 뭔가 빠졌나요? 아니면 내가 너무 게으른가요?
답변
저는 최근에 정확히 목록을지도로 변환해야 할 필요성을 발견했습니다. 이 질문은 Groovy 버전 1.7.9가 나오기 전에 게시되었으므로 collectEntries
아직 메서드 가 존재하지 않았습니다. 제안 된collectMap
방법 과 똑같이 작동합니다 .
Map rowToMap(row) {
row.columns.collectEntries{[it.name, it.val]}
}
어떤 이유로 이전 Groovy 버전을 사용하는 경우이 inject
방법을 사용할 수도 있습니다 ( 여기에 제안 된대로 ). 이것은 클로저 내부에 하나의 표현식 만 사용하는 약간 수정 된 버전입니다 (문자 저장을 위해!) :
Map rowToMap(row) {
row.columns.inject([:]) {map, col -> map << [(col.name): col.val]}
}
+
연산자도 대신 사용될 수있다 <<
.
답변
“주입”을 확인하십시오. 실제 함수형 프로그래밍은이를 “폴드”라고 부릅니다.
columns.inject([:]) { memo, entry ->
memo[entry.name] = entry.val
return memo
}
그리고 당신이 그것에있는 동안, 당신은 아마도 메타 클래스에서 오른쪽이 아닌 카테고리로 메소드를 정의하고 싶을 것입니다. 이렇게하면 모든 컬렉션에 대해 한 번 정의 할 수 있습니다.
class PropertyMapCategory {
static Map mapProperty(Collection c, String keyParam, String valParam) {
return c.inject([:]) { memo, entry ->
memo[entry[keyParam]] = entry[valParam]
return memo
}
}
}
사용 예 :
use(PropertyMapCategory) {
println columns.mapProperty('name', 'val')
}
답변
이 질문을 받았을 때 groupBy 메서드를 사용할 수 없었습니까 ?
답변
필요한 것이 간단한 키-값 쌍 collectEntries
이면 방법으로 충분합니다. 예를 들면
def names = ['Foo', 'Bar']
def firstAlphabetVsName = names.collectEntries {[it.charAt(0), it]} // [F:Foo, B:Bar]
그러나 키당 여러 값이있는 멀티 맵과 유사한 구조를 원한다면 groupBy
방법 을 사용하고 싶을 것입니다.
def names = ['Foo', 'Bar', 'Fooey']
def firstAlphabetVsNames = names.groupBy { it.charAt(0) } // [F:[Foo, Fooey], B:[Bar]]
답변
또한 Google 컬렉션 ( http://code.google.com/p/google-collections/ )을 사용하는 경우 다음과 같이 할 수 있습니다.
map = Maps.uniqueIndex(list, Functions.identity());
답변
그래 … 조금 더 해봤는데이게 꽤 멋진 방법 인 것 같아 …
def collectMap = {Closure callback->
def map = [:]
delegate.each {
def r = callback.call(it)
map[r[0]] = r[1]
}
return map
}
ExpandoMetaClass.enableGlobally()
Collection.metaClass.collectMap = collectMap
Map.metaClass.collectMap = collectMap
이제 Map 또는 Collection의 모든 하위 클래스에이 메서드가 있습니다.
여기에서는 맵에서 키 / 값을 반전하는 데 사용합니다.
[1:2, 3:4].collectMap{[it.value, it.key]} == [2:1, 4:3]
여기에서는 목록에서지도를 만드는 데 사용합니다.
[1,2].collectMap{[it,it]} == [1:1, 2:2]
이제 내 앱이 시작될 때 호출되는 클래스에 이것을 팝하고이 메서드는 내 코드 전체에서 사용할 수 있습니다.
편집하다:
모든 배열에 메서드를 추가하려면 …
Object[].metaClass.collectMap = collectMap
답변
내장 된 항목을 찾을 수 없지만 ExpandoMetaClass를 사용하면 다음과 같이 할 수 있습니다.
ArrayList.metaClass.collectMap = {Closure callback->
def map = [:]
delegate.each {
def r = callback.call(it)
map[r[0]] = r[1]
}
return map
}
이것은 모든 ArrayLists에 collectMap 메소드를 추가합니다 … List 또는 Collection에 추가하는 것이 작동하지 않는 이유를 잘 모르겠습니다. 다른 질문에 대한 것 같습니다 …하지만 이제 할 수 있습니다 …
assert ["foo":"oof", "42":"24", "bar":"rab"] ==
["foo", "42", "bar"].collectMap { return [it, it.reverse()] }
목록에서 계산 된지도까지 하나의 클로저로 … 정확히 내가 찾던 것입니다.
편집 : 목록 및 컬렉션 인터페이스에 메서드를 추가 할 수없는 이유는 이렇게하지 않았기 때문입니다.
List.metaClass.enableGlobally()
메서드 호출 후 인터페이스에 메서드를 추가 할 수 있습니다.이 경우에는 내 collectMap 메서드가 다음과 같은 범위에서 작동 함을 의미합니다.
(0..2).collectMap{[it, it*2]}
지도를 생성합니다. [0 : 0, 1 : 2, 2 : 4]