Scala에서 immutable.Map을 mutable.Map으로 어떻게 변환 할 수 있습니까?


93

어떻게 변환 할 수 있습니다 immutable.Map에 mutable.Map에 내가 값을 업데이트 할 수 있도록 스칼라 Map?

답변:


126

가장 깨끗한 방법은 mutable.Mapvarargs 공장 을 사용하는 것 입니다. ++접근 방식 과 달리 이것은 CanBuildFrom메커니즘을 사용 하므로이를 활용하기 위해 라이브러리 코드를 작성하면 더 효율적일 수 있습니다.

val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*) 

이것은 Map쌍의 시퀀스로도 볼 수 있기 때문에 작동합니다 .


2
매개 변수를 전달할 때 두 번째 줄에서 사용하는 구문을 설명해 주시겠습니까? 콜론은 무엇을합니까?
— Heinzi

7
: _*컴파일러에게 주어진 표현식에 어떤 유형을 할당할지 정확히 알려주는 유형 지정과 매우 유사합니다. 여기서 "이 시퀀스를 가져 와서 여러 vararg 매개 변수로 취급"이라고 생각할 수 있습니다.
— Kevin Wright

16
이것이 가장 깨끗한 경우 컬렉션 라이브러리에 문제가있는 것입니다;)
— matanster

2
@matt 별칭 가져 오기를 사용하면 약간 더 짧게 만들 수 있지만, 불변성을 희생 하는 것은 Scala에게 매우 비관 상적이라는 점을 명심하십시오. , 사본이 아니라면 어떻게 더 깔끔하게 할 것을 제안 할 수 있습니까?
— Kevin Wright

그게 내 요점이지만 할 수는 없지만 더 나은 컬렉션 라이브러리가 IMHO를 가능하게 할 수 있습니다.
— matanster 2015

41
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap

1
이것의 점근 적 시간 복잡성이 모자라는 것을 알고 있습니까? Clojure는 영구 컬렉션을 "일시적인"컬렉션 (즉, 선형 유형의 돌연변이 함수를 가진 가변 컬렉션)으로 전환하고 O(1)단계적 으로 영구 컬렉션으로 되돌릴 수 있다는 것을 알고 있습니다 . 이 외모 가 될 O(n)그 얼마나 영리 구현에 당연히 달려 있지만, ++있다.
— Jörg W Mittag

1
@ Jörg-나는 이것이 O(n). O(n)시간을 절약하기 위해 새 사본의 생성을 연기하거나 원래 맵 대신 변경 세트를 읽어 액세스 시간을 두 배로 늘릴 수 있지만 모든 것을 변경할 때 한계는이어야합니다 . 어느 것이 가장 잘 수행되는지는 아마도 사용 사례에 따라 다릅니다.
— Rex Kerr

1
@Rustem-지도가 순서가 지정되지 않았습니다. 원하는 순서대로 표시됩니다 (해시 맵의 경우 일반적으로 해시 키의 순서입니다). 특히, 불변 맵은 변경 가능한 맵과 다른 아주 작은 맵에 대한 특별한 경우를 가지고 있습니다.
— Rex Kerr

@Rustem Maps는 주문되지 않았습니다.
— Daniel C. Sobral

4

collection.breakOut을 사용하는 것은 어떻습니까?

import collection.{mutable, immutable, breakOut}
val myImmutableMap = immutable.Map(1->"one",2->"two")
val myMutableMap: mutable.Map[Int, String] = myImmutableMap.map(identity)(breakOut)

그것은 이다 멋진하지만, 같이 기본적으로 같은 일을 mutable.Map#applyA가 더 상용구 비트와.
— Kevin Wright

4

시작 Scala 2.13, .to(factory)다음 과 함께 적용된 팩토리 빌더를 통해 :

Map(1 -> "a", 2 -> "b").to(collection.mutable.Map)
// collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")

1

Mapimmutable에서 가져온 기본값을 가진 빈 mutable을 만드는 변형이 있습니다 Map. 언제든지 값을 저장하고 기본값을 재정의 할 수 있습니다.

scala> import collection.immutable.{Map => IMap}
//import collection.immutable.{Map=>IMap}

scala> import collection.mutable.HashMap
//import collection.mutable.HashMap

scala> val iMap = IMap(1 -> "one", 2 -> "two")
//iMap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,one), (2,two))

scala> val mMap = new HashMap[Int,String] {      
     | override def default(key: Int): String = iMap(key)
     | }
//mMap: scala.collection.mutable.HashMap[Int,String] = Map()

scala> mMap(1)
//res0: String = one

scala> mMap(2)
//res1: String = two

scala> mMap(3)
//java.util.NoSuchElementException: key not found: 3
//  at scala.collection.MapLike$class.default(MapLike.scala:223)
//  at scala.collection.immutable.Map$Map2.default(Map.scala:110)
//  at scala.collection.MapLike$class.apply(MapLike.scala:134)
//  at scala.collection.immutable.Map$Map2.apply(Map.scala:110)
//  at $anon$1.default(<console>:9)
//  at $anon$1.default(<console>:8)
//  at scala.collection.MapLike$class.apply(MapLike.scala:134)....

scala> mMap(2) = "three"

scala> mMap(2)          
//res4: String = three

주의 사항 (Rex Kerr의 주석 참조) : 변경 불가능한 맵에서 오는 요소를 제거 할 수 없습니다.

scala> mMap.remove(1)
//res5: Option[String] = None

scala> mMap(1)
//res6: String = one

3
이는 경우에 따라 유용하지만 기본지도에 있던 새지도에서 요소를 제거 할 수 없습니다. 기본값을 덮고 폭로 할 수만 있습니다.
— Rex Kerr

맞습니다,이 솔루션은 부분적입니다.
— Alexander Azarov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.