What is best practice to get a instance in Seq ?
case class Point(x: Int, y: Int)
val points: Seq[Point] = Seq(Point(1, 10), Point(2, 20), Point(3, 30))
I'd like to acquire Point with the maximum of y. (in this case: Point(3, 30))
What's best way ?
The easiest way would be to use TraversableOnce.maxBy:
val points: Seq[Point] = Seq(Point(1, 10), Point(2, 20), Point(3, 30))
scala> points.maxBy(_.y)
res1: Point = Point(3,30)
#YuvalItzchakov's answer is correct but here another way to do it using Ordering :
val points: Seq[Point] = Seq(Point(1, 10), Point(2, 20), Point(3, 30))
// points: Seq[Point] = List(Point(1,10), Point(2,20), Point(3,30))
val order = Ordering.by((_: Point).y)
// order: scala.math.Ordering[Point] = scala.math.Ordering$$anon$9#5a2fa51f
val max_point = points.reduce(order.max)
// max_point: Point = Point(3,30)
or
points.max(order)
// Point = Point(3,30)
or with implicit Ordering:
{
implicit val pointOrdering = Ordering.by((_: Point).y)
points.max
}
// Point = Point(3,30)
Note: TraversableOnce.maxBy uses also implicit Ordering. Reference.
Another way of doing it is by using foldleft.
val points:Seq[Point] = Seq(Point(1,10),Point(2,20),Point(3,30))
points.foldLeft[Point](Point(0,0)){(z,f) =>if (f.y>z.y) f else z}
Related
I am trying to use println to print the output in a certain format but not able to get.
val vgdataLines = sc.textFile("hdfs:///user/ashhall1616/bdc_data/assignment/t1/vgsales-small.csv")
val vgdata = vgdataLines.map(_.split(";"))
val countPublisher = vgdata.map(r => (r(4),1))
val totalcount= countPublisher.count().toInt
val reducePublisher = countPublisher.reduceByKey(_+_)
def toPercentage(x: Int): Double = {x * 100/totalcount}
val top50 = countPublisher.map(r => (r._1, r._2, toPercentage(r._2)))
val top50desc= top50.sortBy(_._2, false)
println(top50desc.take(50))
Expected output format:
(Ubisoft,3,15.0)
(Activision,3,15.0)
(Electronic Arts,2,10.0)
(Nintendo,2,10.0)
(Acclaim Entertainment,1,5.0)
(Sega,1,5.0)
(3DO,1,5.0)
(Namco Bandai Games,1,5.0)
Format I am getting:
res1: Array[(String, Int, Double)] = Array((Sony Computer Entertainment,1,5.0), (Activision,1,5.0), (Nintendo,1,5.0), (Activision,1,5.0), (Nintendo,1,5.0), (3DO,1,
5.0), (Sega,1,5.0), (TDK Mediactive,1,5.0), (Capcom,1,5.0), (Atari,1,5.0), (Konami Digital Entertainment,1,5.0), (Namco Bandai Games,1,5.0), (Electronic Arts,1,5.0
), (Kalypso Media,1,5.0), (Ubisoft,1,5.0), (Ubisoft,1,5.0), (Electronic Arts,1,5.0), (Ubisoft,1,5.0), (Acclaim Entertainment,1,5.0), (Activision,1,5.0))
This is when I use top50desc.take(50) instead of println(top50desc.take(50))
Given
val l = List[(String, Int, Double)](
("Ubisoft", 3, 15.0),
("Activision", 3, 15.0),
("Electronic Arts", 2, 10.0)
)
note the difference between printing each element of the collection
l.foreach(println)
// (Ubisoft,3,15.0)
// (Activision,3,15.0)
// (Electronic Arts,2,10.0)
and printing the collection itself
println(l)
// List((Ubisoft,3,15.0), (Activision,3,15.0), (Electronic Arts,2,10.0))
foreach is intendend for when we wish to apply some side-effect, such as printing, to each element.
I have a list with 5 elements
data = List((List(c1),Y), (List(c1),N), (List(c1),N), (List(c1),Y), (List(c1),Y))
And I want to create a list following:
List((List(c1),Y,0.666), (List(c1),N),0.333)
Any tips on the best way to do this?
I am using scala if that's any help
object Grouping {
def main(args: Array[String]): Unit = {
val data = List((List("c1"),"Y"), (List("c1"),"N"), (List("c1"),"N"), (List("c1"),"Y"), (List("c1"),"Y"))
val result = data.groupBy(grp => (grp._1,grp._2))
.mapValues(count => BigDecimal(count.size.toDouble).setScale(3)./(BigDecimal(data.size.toDouble).setScale(3))
.setScale(3, BigDecimal.RoundingMode.HALF_UP))
.map( k => (k._1._1,k._1._2,k._2)).toList
println("result=="+result)
}
}
def calculatePercentages(data : List[(List[String], String)]): List[((List[String], String),BigDecimal)] = {
val (yesRows, noRows) = data.partition(_._2 == "Y")
List((yesRows(0), (BigDecimal(yesRows.length) / BigDecimal(data.length)).setScale(3, BigDecimal.RoundingMode.HALF_UP)),
(noRows(0), (BigDecimal(noRows.length) / BigDecimal(data.length)).setScale(3, BigDecimal.RoundingMode.HALF_UP)))
}
scala> calculatePercentages(data)
res30: List[((List[String], String), BigDecimal)] = List(((List(c1),Y),0.600), ((List(c1),N),0.400))
Thank you very much for your support. Your code ran properly on my first request. However, with more complex data as with a list below it is not as I expected.
List(
(List(c1, a1),Y),
(List(a1),Y),
(List(c1, a1),N),
(List(a1),N),
(List(a1),Y))
and i want the result is
List(
(List(c1, a1),Y, 0.5),
(List(c1, a1),N, 0.5),
(List(a1),Y, 0.66),
(List(a1),N, 0.33),
)
I look forward to your support
I want to find a percentage from the value of a key, value pair which is stored in the map.
For eg: Map('a'->10,'b'->20).I need to find percentage occurance of 'a' and 'b'
Adding to Thilo's answer, you can try this below code. The final result will again be a Map[String, Double].
val map = Map("a" -> 10.0, "b" -> 20.0)
val total = map.values.sum
val mapWithPerc = map.mapValues(x => (x * 100) / total)
println(mapWithPerc)
//prints Map(a -> 33.333333333333336, b -> 66.66666666666667)
def mapToPercentage(key: String)(implicit map: Map[String, Double]) = {
val valuesSum = map.values.sum
(map(key) * 100) / valuesSum
}
implicit val m: Map[String, Double] = Map("a" -> 10, "b" -> 20, "c" -> 30)
println(mapToPercentage("a")) // 16.666666666666668
println(mapToPercentage("b")) // 33.333333333333336
println(mapToPercentage("c")) // 50
See demo here
Note: there is absolutely no need to curry the function parameters or make the map implicit. I just think it looks nicer in this example. Something like def mapToPercentage(key: String, map: Map[String, Double]) = {...} and mapToPercentage("a", m) is also perfectly valid. That being said, if you want to get even fancier:
implicit class MapToPercentage (map: Map[String, Double]) {
def getPercentage(key: String) = {
val valuesSum = map.values.sum
(map(key) * 100) / valuesSum
}
}
val m: Map[String, Double] = Map("a" -> 10, "b" -> 20, "c" -> 30)
println(m.getPercentage("a")) // 16.666666666666668
println(m.getPercentage("b")) // 33.333333333333336
println(m.getPercentage("c")) // 50
See demo here
Point being, the logic behind getting the percentage can be written a few ways:
(map(key) * 100) / valuesSum // get the value corresponding to a given key,
// multiply by 100, divide by total sum or all values
// - will complain if key doesn't exist
(map.getOrElse(key, 0D) * 100) / valuesSum // more safe than above, will not fail
// if key doesn't exist
map.get(key).map(_ * 100 / valuesSum) // will return None if key doesn't exist
// and Some(result) if key does exist
val map = Map('a' -> 10, 'b' -> 20)
val total = map.values.sum
map.get('a').map(_ * 100 / total) // gives Some(33)
I am working on an exercise to calculate stock basis given a list of stock purchases in the form of thruples (ticker, qty, stock_price). I've got it working, but would like to do the calculation part in more of a functional way. Anyone have an answer for this?
// input:
// List(("TSLA", 20, 200),
// ("TSLA", 20, 100),
// ("FB", 10, 100)
// output:
// List(("FB", (10, 100)),
// ("TSLA", (40, 150))))
def generateBasis(trades: Iterable[(String, Int, Int)]) = {
val basises = trades groupBy(_._1) map {
case (key, pairs) =>
val quantity = pairs.map(_._2).toList
val price = pairs.map(_._3).toList
var totalPrice: Int = 0
for (i <- quantity.indices) {
totalPrice += quantity(i) * price(i)
}
key -> (quantity.sum, totalPrice / quantity.sum)
}
basises
}
This looks like this might work for you. (updated)
def generateBasis(trades: Iterable[(String, Int, Int)]) =
trades.groupBy(_._1).mapValues {
_.foldLeft((0,0)){case ((tq,tp),(_,q,p)) => (tq + q, tp + q * p)}
}.map{case (k, (q,p)) => (k,q,p/q)} // turn Map into tuples (triples)
I came up with the solution below. Thanks everyone for their input. I'd love to hear if anyone had a more elegant solution.
// input:
// List(("TSLA", 20, 200),
// ("TSLA", 10, 100),
// ("FB", 5, 50)
// output:
// List(("FB", (5, 50)),
// ("TSLA", (30, 166)))
def generateBasis(trades: Iterable[(String, Int, Int)]) = {
val groupedTrades = (trades groupBy(_._1)) map {
case (key, pairs) =>
key -> (pairs.map(e => (e._2, e._3)))
} // List((FB,List((5,50))), (TSLA,List((20,200), (10,100))))
val costBasises = for {groupedTrade <- groupedTrades
tradeCost = for {tup <- groupedTrade._2 // (qty, cost)
} yield tup._1 * tup._2 // (trade_qty * trade_cost)
tradeQuantity = for { tup <- groupedTrade._2
} yield tup._1 // trade_qty
} yield (groupedTrade._1, tradeQuantity.sum, tradeCost.sum / tradeQuantity.sum )
costBasises.toList // List(("FB", (5, 50)),("TSLA", (30, 166)))
}
As the title says, is there any Scala library that exports functions to convert, preferably fluently, a byte array to an Int, to a Long or to a Double?
I need something compatible with 2.9.1 and FOSS.
If you happen to know exactly what I need and where to find it, a line for SBT and a line for an example will be enough! :)
If there's no such thing as what I'm looking for, the closest thing in Java will also work...
You can use Java NIO's ByteBuffer:
import java.nio.ByteBuffer
ByteBuffer.wrap(Array[Byte](1, 2, 3, 4)).getInt
ByteBuffer.wrap(Array[Byte](1, 2, 3, 4, 5, 6, 7, 8)).getDouble
ByteBuffer.wrap(Array[Byte](1, 2, 3, 4, 5, 6, 7, 8)).getLong
No extra dependencies required.
You can also use BigInt from the scala standard library.
import scala.math.BigInt
val bytearray = BigInt(1337).toByteArray
val int = BigInt(bytearray)
Java's nio.ByteBuffer is the way to go for now:
val bb = java.nio.ByteBuffer.allocate(4)
val i = 5
bb.putInt(i)
bb.flip // now can read instead of writing
val j = bb.getInt
bb.clear // ready to go again
You can also put arrays of bytes, etc.
Keep in mind the little/big-endian thing. bb.order(java.nio.ByteOrder.nativeOrder) is probably what you want.
For Double <-> ByteArray, you can use java.lang.Double.doubleToLongBits and java.lang.Double.longBitsToDouble.
import java.lang.Double
def doubleToByteArray(x: Double) = {
val l = java.lang.Double.doubleToLongBits(x)
val a = Array.fill(8)(0.toByte)
for (i <- 0 to 7) a(i) = ((l >> ((7 - i) * 8)) & 0xff).toByte
a
}
def byteArrayToDouble(x: Array[scala.Byte]) = {
var i = 0
var res = 0.toLong
for (i <- 0 to 7) {
res += ((x(i) & 0xff).toLong << ((7 - i) * 8))
}
java.lang.Double.longBitsToDouble(res)
}
scala> val x = doubleToByteArray(12.34)
x: Array[Byte] = Array(64, 40, -82, 20, 122, -31, 71, -82)
scala> val y = byteArrayToDouble(x)
y: Double = 12.34
Or ByteBuffer can be used:
import java.nio.ByteBuffer
def doubleToByteArray(x: Double) = {
val l = java.lang.Double.doubleToLongBits(x)
ByteBuffer.allocate(8).putLong(l).array()
}
def byteArrayToDouble(x:Array[Byte]) = ByteBuffer.wrap(x).getDouble
The following worked for me using Scala:
import org.apache.kudu.client.Bytes
Bytes.getFloat(valueToConvert)
You can also use:
Bytes.toInt(byteArray)
Worked like a charm!