Scala SortedSet - 按一个排序排序并按其他顺序排序? [英] Scala SortedSet - sorted by one Ordering and unique by something else?

查看:26
本文介绍了Scala SortedSet - 按一个排序排序并按其他顺序排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一组字符串,我想按长度排序,但按正常的 String 唯一性是唯一的.我的意思是我可以在 Set 中拥有多个相同长度的 String,但它们应该按长度排序.

Say I have a set of Strings that I want to be ordered by length but unique by the normal String uniqueness. What I mean is that I that I could have more than one String of same length in the Set, but that they should be sorted by length.

我想这样表达顺序:

val orderByLength = Ordering[Int].on[String](_ length)

我认为它看起来非常好.但是如果我要把它扔进一个 SortedSet,像这样说:

which I think looks really nice. But if I were to throw this into a SortedSet, say like this:

scala> val s = SortedSet("foo", "bar")(orderByLength)
s: scala.collection.immutable.SortedSet[java.lang.String] = TreeSet(bar)

我只得到'bar'.这是因为 Ordering 表示总排序,因此当 compare 返回 0 时,元素被认为是相同的.

I only get 'bar'. This is because the Ordering represents a total ordering and so when compare returns 0 the elements are considered identical.

因此,我想我需要进行链式排序并比较长度是否相等的字符串.为此,我使用了pimp my library"模式,如下所示:

Therefore I'm thinking I need to make a chained ordering and compare the Strings if the lengths are equal. To do this I used the "pimp my library"-pattern like this:

trait ChainableOrderings {
  class ChainableOrdering[T](val outer: Ordering[T]) {
    def ifEqual(next: Ordering[T]): Ordering[T] = new Ordering[T] {
      def compare(t1: T, t2: T) = {
        val first = outer.compare(t1, t2)
        if (first != 0) first else next.compare(t1, t2)
      }
    }
  }
  implicit def chainOrdering[T](o: Ordering[T]) = new ChainableOrdering[T](o)
}

我可以像这样使用:

val ordering = Ordering[Int].on[String](_ length) ifEqual Ordering[String]

我觉得它看起来真的很棒,但后来我意识到我想要做的并不是真正按照字符串的自然顺序排序,我只是想按大小排序,而是通过其他东西的唯一性.这可能以更优雅的方式实现吗?

I thought it looked really great, but then I realized that what I wanted to do was not really to order by the natural ordering of Strings, I just wanted ordering by size, but uniqueness by something else. Is this possible in a more elegant way?

推荐答案

我在这种情况下的做法是:

What I do in such situations is this:

val orderByLength = Ordering[(Int, String)].on[String](s => s.length -> s)

换句话说,使用元组来获得决胜局.

In other words, use a tuple to get a tie-breaker.

另一方面,我认为 SortedSet 根据元素的 排序 将元素视为相同是愚蠢的.我认为这之前已经讨论过,但我不会放弃搜索邮件列表档案和 scala trac 以获得讨论/票证的可能性,并且可能试图让 SortedSet 改变其行为.

On the other hand, I think it's silly of SortedSet to consider elements the same based on their ordering. I think this has been discussed before, but I wouldn't discard the possibility of searching mailing lists archives and the scala trac for discussions/tickets on this, and maybe trying to get SortedSet to change its behavior.

这篇关于Scala SortedSet - 按一个排序排序并按其他顺序排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆