在与 Scala 的同一行中有条件地使用 .reverse
Conditionally using .reverse in the same line with Scala
我在 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)
我不太确定你是否可以访问这里的布尔参数,但你可以按如下方式解决这个问题:
.top(num)(if (booleanParameter) Ordering[(Int, Int)].reverse else Ordering[(Int, Int)])
解决方案0
正如 nicodp 已经指出的那样,如果范围内有一个布尔变量 b
,您可以简单地替换表达式
Ordering[(Int, Int)]
通过 if
-表达式
if (b) Ordering[(Int, Int)] else Ordering[(Int, Int)].reverse
我不得不承认这是我能想到的最短、最清晰的解决方案。
但是...我不太喜欢表达式 Ordering[(Int, Int)]
在代码中出现 两次 。在这种情况下这并不重要,因为它很短,但是如果表达式更长一点呢?显然,甚至 。
所以,我想出了一些方法来不重复 子表达式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)
我在 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)
我不太确定你是否可以访问这里的布尔参数,但你可以按如下方式解决这个问题:
.top(num)(if (booleanParameter) Ordering[(Int, Int)].reverse else Ordering[(Int, Int)])
解决方案0
正如 nicodp 已经指出的那样,如果范围内有一个布尔变量 b
,您可以简单地替换表达式
Ordering[(Int, Int)]
通过 if
-表达式
if (b) Ordering[(Int, Int)] else Ordering[(Int, Int)].reverse
我不得不承认这是我能想到的最短、最清晰的解决方案。
但是...我不太喜欢表达式 Ordering[(Int, Int)]
在代码中出现 两次 。在这种情况下这并不重要,因为它很短,但是如果表达式更长一点呢?显然,甚至
所以,我想出了一些方法来不重复 子表达式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)