gpt4 book ai didi

scala - SortedSet 映射并不总是保留结果中的元素排序?

转载 作者:行者123 更新时间:2023-12-04 16:53:19 25 4
gpt4 key购买 nike

鉴于以下 Scala 2.9.2 代码:

更新了非工作示例

import collection.immutable.SortedSet

case class Bar(s: String)

trait Foo {
val stuff: SortedSet[String]
def makeBars(bs: Map[String, String])
= stuff.map(k => Bar(bs.getOrElse(k, "-"))).toList
}

case class Bazz(rawStuff: List[String]) extends Foo {
val stuff = SortedSet(rawStuff: _*)
}


// test it out....
val b = Bazz(List("A","B","C"))
b.makeBars(Map("A"->"1","B"->"2","C"->"3"))
// List[Bar] = List(Bar(1), Bar(2), Bar(3))
// Looks good?

// Make a really big list not in order. This is why we pass it to a SortedSet...
val data = Stream.continually(util.Random.shuffle(List("A","B","C","D","E","F"))).take(100).toList
val b2 = Bazz(data.flatten)

// And how about a sparse map...?
val bs = util.Random.shuffle(Map("A" -> "1", "B" -> "2", "E" -> "5").toList).toMap
b2.makeBars(bs)
// res24: List[Bar] = List(Bar(1), Bar(2), Bar(-), Bar(5))

我发现,在某些情况下, makeBars扩展类的方法 Foo不返回排序列表。实际上,列表排序并不反射(reflect) SortedSet 的排序。

我在上面的代码中遗漏了什么,其中 Scala 不会总是映射 SortedSetList元素按 SortedSet 排序订购?

最佳答案

您对隐式解析感到惊讶。
map方法需要一个 CanBuildFrom与目标集合类型(在简单情况下,与源集合类型相同)和映射器函数的返回类型兼容的实例。

SortedSet 的特殊情况下,其隐含 CanBuildFrom需要一个 Ordering[A] (其中 A 是映射器函数的返回类型)可用。当您的 map 函数返回编译器已经知道如何查找 Ordering 的内容时因为,你很好:

scala> val ss = collection.immutable.SortedSet(10,9,8,7,6,5,4,3,2,1)
ss: scala.collection.immutable.SortedSet[Int] = TreeSet(1, 2, 3, 4, 5,
6, 7, 8, 9, 10)

scala> val result1 = ss.map(_ * 2)
result1: scala.collection.immutable.SortedSet[Int] = TreeSet(2, 4, 6, 8, 10,
12, 14, 16, 18, 20)
// still sorted because Ordering[Int] is readily available

scala> val result2 = ss.map(_ + " is a number")
result2: scala.collection.immutable.SortedSet[String] = TreeSet(1 is a number,
10 is a number,
2 is a number,
3 is a number,
4 is a number,
5 is a number,
6 is a number,
7 is a number,
8 is a number,
9 is a number)
// The default Ordering[String] is an "asciibetical" sort,
// so 10 comes between 1 and 2. :)

但是,当您的映射器函数返回一个未知排序的类型时, SortedSet 上的隐式不匹配(具体来说,找不到其隐式参数的值),因此编译器看起来“向上”以寻找兼容的 CanBuildFrom并从 Set 中找到通用的.
scala> case class Foo(i: Int)
defined class Foo

scala> val result3 = ss.map(Foo(_))
result3: scala.collection.immutable.Set[Foo] = Set(Foo(10), Foo(4), Foo(6), Foo(7), Foo(1), Foo(3), Foo(5), Foo(8), Foo(9), Foo(2))

// The default Set is a hash set, therefore ordering is not preserved

当然,你可以通过简单地提供一个 Ordering[Foo] 的实例来解决这个问题。它可以满足您的期望:
scala> implicit val fooIsOrdered: Ordering[Foo] = Ordering.by(_.i)
fooIsOrdered: Ordering[Foo] = scala.math.Ordering$$anon$9@7512dbf2

scala> val result4 = ss.map(Foo(_))
result4: scala.collection.immutable.SortedSet[Foo] = TreeSet(Foo(1), Foo(2),
Foo(3), Foo(4), Foo(5),
Foo(6), Foo(7), Foo(8),
Foo(9), Foo(10))
// And we're back!

最后,请注意玩具示例通常不会出现问题,因为 Scala 集合库对小型 (n <= 6) 集合和映射具有特殊的实现。

关于scala - SortedSet 映射并不总是保留结果中的元素排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19528357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com