How would I write the following Java code in Scala? The intention is to traverse a tree structure and return the first element that matches a predicate.
public class MyObject {
private String id;
private List<MyObject> children;
public MyObject findById(String otherId) {
if (this.id.equals(otherId)) {
return this;
} else {
for (MyObject child : children) {
MyObject found = child.findById(otherId);
if (found != null) {
return found;
}
}
return null;
}
}
}
The scala would look something like this but I don't know what to put in the else clause.
class MyObject(id: String, children: List[MyObject]) {
def findById(otherId: String): Option[MyObject] = {
if (this.id == otherId) {
Some(this)
} else {
//What goes here?
}
}
}
You should implement a tail recursive search, so you won't get a stack overflow:
class MyObject(val id: String, val children: List[MyObject]) {
def findById(otherId: String): Option[MyObject] = {
#tailrec
def recurseOverChildren(list: List[MyObject]): Option[MyObject] = {
list match {
case Nil => None
case head :: tail =>
if(head.id == otherId) Some(head)
else recurseOverChildren(tail ++ head.children)
}
}
recurseOverChildren(List(this))
}
}
The recursion is simple, we just check if the head of the list is the item we're searching for. If not we add it's children to the end of the list. If the list is empty the item is not in the tree. We initialize the search with a list containing one element: the element the function was invoked upon.
This will be a breadth first search, if you would like a depth first search then append the children in front of the list, not at the end.
Related
I'm trying to implement a streaming process on Kafka. The data structure that I'm using looks like this one:
trait Base {def baseField: String}
final case class Elem0(baseField: String, oil: String, oil2: String) extends Base
final case class Elem1(baseField: String, engine: String, engine2: String) extends Base
final case class Elem2(baseField: String, tire: String, tire2: String) extends Base
This is just a simplification, the real "ElemX" classes (and the Base) have many more fields. The main App receives different objects of each of the classes using different Kafka topics. Each object needs to be processed independently.
I need to implement a function that does some complicated logic depending on the values of the fields of "ElemX". The possible values of "oil", "engine" and "tire" are the same for all classes (let's say that they can be "X", "Y", "Z"). I mean, there are just 3 possible values for all the case classes' fields. So my first approach is something like this:
def doSomethingWithElem0(record: Elem0) = {
if (record.oil == "X") {
... // logic1
} else if (record.oil == "Y") {
... // logic2
} else {
... // logic3
}
if (record.oil2 == "X") {
... // logic1
} else if (record.oil2 == "Y") {
... // logic2
} else {
... // logic3
}
...
}
def doSomethingWithElem1(record: Elem1) = {
if (record.engine == "X") {
... // logic1
} else if (record.engine == "Y") {
... // logic2
} else {
... // logic3
}
if (record.engine2 == "X") {
... // logic1
} else if (record.engine2 == "Y") {
... // logic2
} else {
... // logic3
}
...
}
def doSomethingWithElem2(record: Elem2) = {
if (record.tire == "X") {
... // logic1
} else if (record.tire == "Y") {
... // logic2
} else {
... // logic3
}
if (record.tire2 == "X") {
... // logic1
} else if (record.tire2 == "Y") {
... // logic2
} else {
... // logic3
}
...
}
As you can see there is a lot of duplicated logic but it all depends on the values of the case class fields. I cannot have something like this:
if (record.tire == "X" || record.tire2 == "X") {
// logic1
}
Because the logic involves doing something with each of the field values. This logic involves checking that specific value on a Redis database and things like checking the last time a certain value was received (for instance, I need to check if the value of record.tire was stored previously and do some calculations based on this). The key point is that I want to "apply" the same logic for all the case class fields without having to go over each record.field
Is there any way I could simplify this logic? I've been checking libraries like shapeless but I don't know if I can apply this kind of functions here.
Any help would be greatly appreciated.
Well, case classes are Products, so if you are talking about iterating over a case class fields, and applying the same logic to them, you could do something like:
record.productIterator.tail.foreach {
case "X" => logic1()
case "Y" => logic2()
case _ => logic3()
}
I have a class where I want a conditional Elem in xml to be added, but I am unable to do this. Please help.
The ShortName block is supposed to be conditional.
While debugging I see that get shortname gets executed. In fact if I try wrapping that in a dummy tag (<dummy>{getShortName().get}</dummy> ) everything works. But I need the condition outside.
Here's my class:
import scala.xml.Elem
class MyClass(rob: ROB, scalaDTO: ScalaDTO, robStatus: Status) {
val myRob =
<FeatureNames>
{val allPoiNames = rob.Identity.Names.get.ROB_Name
allPoiNames.map(robName => {
if (!robName.Type.contains("Shortened")) {
<FeatureName CaseAutoCorrectionEnabled="true">
{robName.Text.map(text => {
val transType = text.Trans_Type
transType match {
case None => {
{
<Name>
{text.value}
</Name>
{
//Executes but does not get added
getShortName().getOrElse(null)
}
<Language>
{robName.Language_Code}
</Language>
}
}
case _ => {
<OtherName>
{text.value}
</OtherName>
}
}
})}
</FeatureName>
}
})}
</FeatureNames>
private def getShortName(): Option[Elem] = {
val condition = true
if (condition) {
Some(
<ShortName>ShortName</ShortName>
)
} else {
None
}
}
override def toString: String = {
val prettyPrinter = new scala.xml.PrettyPrinter(150, 2)
prettyPrinter.format(scala.xml.Utility.trim(myRob))
}
}
My output looks like:
<FeatureNames>
<FeatureName CaseAutoCorrectionEnabled="true">
<Language>ENF</Language>
<OtherName>The Name</OtherName>
</FeatureName>
</FeatureNames>
Note the Missing Name Tag,moving it below the getShortName() line prints it fine
For this kind of logic, you can express it as a NodeSeq instead of mixing it in with xml literals.
Something like:
case None =>
NodeSeq.fromSeq(Seq(<Name>{text.value}</Name>, getShortName().orNull, <Language>{robName.Language_Code}</Language>))
I'm new to Scala, I'm trying to transform and add an object while iterating a list in Scala, but struggling badly with syntax and probably concept as well.
I want to achieve something like below as we do in JAVA.
public Set<Manager> promoteEmployeesToManager(List<Employee> employees) {
Set<Manager> managers = new HashSet<Manager>();
for(employee: employees){
if(employee.getExprience() > 5) {
managers.add(promoteEmployee(employee));
}
}
return managers;
}
public Manager promoteEmployee(Employee employee){
return new Manager(employee);
}
I tried below code but it's not working. In the step of saveNewManagers(newManagers.toArray); the newManagers is still empty.
private def processEmployeePromotion(employees : List[Employee]) {
val newManagers: Set[Manager] = Set()
employees.asScala.map(employee => promoteEmployee(newManagers, employee))
saveNewManagers(newManagers.toArray);
}
Then promoteEmployee method is like:
private def promoteEmployee (newManagers : Set[Manager], employee: Employee){
if(employee.getExprience() > 5) {
managers+.(new Manager(employee));
}
}
So you have a List of employees and you want a List of new managers.
def processEmployeePromotion(employees :List[Employee]) :List[Manager] =
employees.collect{case emp if emp.getExprience() > 5 => promoteEmployee(emp)}
This will return an empty List if the employees list is empty or if no employees qualify for promotion.
val managers: Set[Manager] = employees
.iterator
.filter(_.getExperience > 5)
.map(promoteEmployee)
.toSet
In Scala, Set is immutable by default, so the + method on Set returns a new set.
private def promoteEmployee(managers: Set[Manager], employee: Employee): Set[Manager] =
if (employee.getExperience > 5) {
managers + new Manager(employee)
} else {
managers
}
private def processEmployeePromotion(employees: List[Employee]): Unit = {
val newManagers = employees.asScala.foldLeft(Set.empty[Manager]) { (managers, employee) =>
promoteEmployee(managers, employee)
}
saveNewManagers(newManagers.toArray)
}
The major change here is the foldLeft which basically abstracts away the idea of looping and building up the Set.
An alternative strategy would be to have promoteEmployee return an Option[Manager]; you can think of Option as being like a collection of at most one element.
private def promoteEmployee(employee: Employee): Option[Manager] =
if (employee.getExperience > 5) {
Option(new Manager(employee))
} else {
None
}
private def promotedEmployees(employees: Iterable[Employee]): Set[Manager] =
employees.flatMap(promoteEmployee).toSet // NB: might not work if Manager doesn't obey the equality contract...
private def processEmployeePromotion(employees: List[Employee]): Unit = {
saveNewManagers(promotedEmployees(employees.asScala).toArray)
}
When you start to work with Scala you have to get used to work with immutable data structures, foldables, expressions... etc . You can still work with mutable as you used to do with Java if you want but the first is what you should do.
Look at this example using foldLeft from List:
case class Employee(id: String, name: String, experience: Int)
case class Manager(employee: Employee)
object Your_Code extends App {
def promoteEmployee(employee: Employee) =
Manager(employee)
def promoteEmployeesToManager(list: List[Employee]) : Set[Manager] = {
list.foldLeft(Set[Manager]())((a, b) => if(b.experience > 5) a + promoteEmployee(b) else a)
}
val employess = List(Employee("id1", "name1", 6), Employee("id1", "name1", 4))
println(promoteEmployeesToManager(employess))
}
I'm learning Scala and am making some Stack implementations as practice. I made this and there are some apparent issues.
class LinkedStack[T] extends Stack[T] {
var current: Node = null
var n: Int = 0
private class Node(e: T, prev: Node) {
val element: T = e
var previous: Node = prev
}
override def pop(): T = {
if (n == 0) {
throw new NoSuchElementException
}
val popNode: Node = current
current = current.previous
popNode.previous = null
n -= 1
popNode.element
}
override def peek(): T = {
if (n == 0) {
throw new NoSuchElementException
}
current.element
}
override def push(element: T): Unit = {
if (element == null) {
throw new NullPointerException
}
val newNode: Node = new Node(element, current)
current = newNode
n += 1
}
override def size(): Int = {
n
}
override def toString(): String = {
val builder = new StringBuilder("Stack top [")
var temp: Node = current
if (n == 0) {
builder.append("]")
return builder.toString()
}
while (temp.previous != null) {
builder.append(temp.element).append(", ")
temp = temp.previous
}
builder.append(temp.element).append("]")
builder.toString()
}
}
The trait includes all of the elements except toString. My main problem is that I'm using null pretty liberally. I know this shouldn't be done at all in Scala, and the line
var current: Node = null
in the constructor generates a compile error. How should I implement a constructor to create an empty stack? What's the best substitution for null?
Edit:
You may have noticed that the Node class should be rewritten as
private class Node(val element: T, var previous: Node) {}
I realized this after reading Rex Kerr's answer. I forgot that I was programming in Scala when I first wrote that.
There's nothing terribly wrong with using null as part of the internals for your class as long as those nulls never leak out and the logic is straightforward enough so you can be sure of that.
But if you want to not use null for practice, you have two choices. One is to use a built-in alternative: instead of Node use Option[Node] and use None for null. Given that your list is invariant, this is the easier way.
Second, you can replace Node with a hierarchy like so:
trait Node
class Elt(val element: T, val previous: Node) extends Node {}
object End extends Node
And then you use End wherever you use null now, and match on the Node any time you need to walk or do something, e.g.
def peek = current match {
case End => throw new NoSuchElementException
case Elt(e, _) => e
}
Of course this means each list has to create an extra object (End), and there are various other drawbacks, most of which can be gotten around to some extent. But for an exercise in avoiding null, you can ignore those complications.
i'm also scala learning my stack implementation ,it;s simple i used scala mutable array buffer
object Stack{
var stack=scala.collection.mutable.ArrayBuffer[Int]()
def isEmpty():Boolean={
if(stack.length==0) true
else false
}
def push(input:Int):Unit={
stack+=input
}
def size():Int={
stack.length
}
def pop():Int={
stack.remove(stack.length-1)
}
def peek()={
stack(stack.length-1)
}
}
With the following definitions:
class Test {
var activated: Boolean = false
}
def maybeTest(): Test = {
if(...) {
val res = new Test
if(...) res.activated = true
} else null
}
I am having a lot of if structures like this one:
val myobject = maybeTest()
if(myobject != null && myobject.activated) {
// Do something that does not care about the object
}
I would like to condensate it a little bit. Is there a nice way to define/write something like this to avoid a nullPointerException:
if(maybeTest() &&> (_.activated)) {
...
}
What is a best way of achieving this in scala?
You can wrap such code in Option like this:
class Test(num: Int) {
def someNum = num
}
val test: Test = null
Option(test).map(t => t.someNum)
In this example if your variable is null then you will get None, otherwise just work with Some(value)
Update
If you don't want to use Option, then you can define such function
class Test(num: Int) {
def give = num
}
def ifDefAndTrue[T, K](obj: T)(ifTrue: T => Boolean)(then: => K) {
if (obj != null && ifTrue(obj))
then
}
In your case this look like this:
val test = new Test // assuming that activated is false
ifDefAndTrue(test)(_.activate) {
println("results in unit")
}
But it contains side effect and not functional
How about
for {m <- Option(maybeTest())
if m.activated
}
{
... // do something with non-null, activated, m
}
Found the best way with implicit classes, which properly handles the null case (although it might not be the most efficient way).
implicit class CheckNull[T](obj: T) {
def call(f: T => Unit): Unit = if(obj != null) f(obj) else ()
def is(f: T => Boolean): Boolean = if(obj != null) f(obj) else false
}
So I can write a type safe method and even calls:
if(maybeTest() is (_.activated)) {
...
}
myObjectMaybeNull call (_.pause())
Note that parenthesis around (_.activated) are necessary.