我在Scala中有一个组合子组合,最后一个是.top
,我可以将其用作.top(num)(Ordering[(Int, Int)].reverse)
,具体取决于布尔参数。
如何根据布尔参数在同一行中实现组合使用或不使用.reverse
组合?我的意思是,没有创建另一个val
来表明是否使用.reverse
?
val mostPopularHero = sparkContext
.textFile("resource/marvel/Marvel-graph.txt") // build up superhero co-apperance data
.map(countCoOccurrences) // convert to (hero ID, number of connections) RDD
.reduceByKey((x, y) => x + y) // combine entries that span more than one line
.map(x => (x._2, x._1)) // flip it from (hero ID, number of connections) to (number of connections, hero ID)
.top(num)(Ordering[(Int, Int)].reverse)
答案 0 :(得分:2)
解决方案0
正如 nicodp 已经指出的那样,如果你在范围内有一个布尔变量b
,你可以简单地替换表达式
Ordering[(Int, Int)]
通过if
- 表达式
if (b) Ordering[(Int, Int)] else Ordering[(Int, Int)].reverse
我必须承认,这是我能想到的最短,最清晰的解决方案。
但是......我不太喜欢表达式Ordering[(Int, Int)]
出现在代码中两次。在这种情况下,它并不重要,因为它很简短,但如果表达式稍微长一点怎么办?显然,即使是Ruby has something for such cases。
所以,我尝试了一些不重复子表达式Ordering[(Int, Int)]
的方法。最好的解决方案是,如果我们在标准库中有一个默认的Id
- monad实现,那么我们可以简单地将一个值包装在pure
中,然后使用布尔值map
。
但标准库中没有Id
。因此,这里有一些其他提案,仅针对有问题的表达式变得更长的情况:
解决方案1
您可以在scala中使用块作为表达式,因此您可以替换上面的内容
Ordering[(Int, Int)]
:
{val x = Ordering[(Int, Int)]; if (b) x else x.reverse}
更新:等等!这比重复的版本短! ;)
解决方案2
定义有条件地反转排序的函数,声明Ordering[(Int, Int)]
作为参数的类型,然后
而不是重新键入Ordering[(Int, Int)]
作为表达式,请使用implicitly
:
((x: Ordering[(Int, Int)]) => if (b) x else x.reverse)(implicitly)
解决方案3
我们没有Id
,但我们可以滥用其他仿函数的构造函数和消除器。例如,可以将复杂表达式包装在List
或Option
中,然后map
,然后解压缩结果。以下是Some
的变体:
Some(Ordering[(Int, Int)]).map{ x => if(b) x else x.reverse }.get
理想情况下,这应该是Id
而不是Some
。请注意,解决方案1执行与默认环境monad类似的操作。
解决方案4
最后,如果您的代码中出现上述模式不止一次,那么引入一些额外的语法来处理它可能是值得的:
implicit class ReversableOrderingOps[X](ord: Ordering[X]) {
def reversedIf(b: Boolean): Ordering[X] = if (b) ord.reverse else ord
}
现在你可以定义这样的排序:
val myConditionHolds = true
val myOrd = Ordering[(Int, Int)] reversedIf myConditionHolds
或直接在你的冗长表达中使用它:
val mostPopularHero = sparkContext
.textFile("resource/marvel/Marvel-graph.txt")
.map(countCoOccurrences)
.reduceByKey((x, y) => x + y)
.map(x => (x._2, x._1))
.top(num)(Ordering[(Int, Int)] reversedIf myConditionHolds)
答案 1 :(得分:1)
我不太确定你是否可以访问布尔参数,但你可以按照以下方式解决这个问题:
.top(num)(if (booleanParameter) Ordering[(Int, Int)].reverse else Ordering[(Int, Int)])