Vladimir Rincon
Vladimir Rincon

Reputation: 11

Recursion List Manipulation on Scala

I have a big problem and I have several days trying to solve it, I hope someone can help me. The problem is the following: I have a list that can have n elements, but depending on the numbers of elements I should apply a function in different ways, as example I have the following code:

if (list.size() == 1){
    p = list.get(0)
    select = new Select(schema,p)
    println(select)
  } else { //If list have 2 elements
    p = list.get(0)
    p1 = list.get(1)
    select = new Select(schema,And(p,p1))
    println(select)
  } else { //If list have 3 elements
    p = list.get(0)
    p1 = list.get(1)
    p2 = list.get(2)
    select = new Select(schema,new And(And(p,p1),p2))
    println(select)
  } else { //If list have 4 elements
    p = list.get(0)
    p1 = list.get(1)
    p2 = list.get(2)
    p3 = list.get(3)
    select = new Select(schema,new And(And(p,p1),And(p2,p3))
    println(select)
  } else { //If list have 5 elements.......... and so on

How can avoid this sucesive conditionals and make that this work. I try with a for loop, but I can not generate new variables, and also I don't know how give a control to the And function.... If you need mor information please let me know

In order to add more information, the And function is a nested loop join that is use on relational databases:

sealed abstract class Pat //patterns
  case class And( p1: Pat, p2: Pat) extends Pat

This have another functions that are using after I get the results of the conditionals described above. The idea also is that I can have n elements on the list, not a fix number, for that reason I think that a match is not an option

Upvotes: 0

Views: 113

Answers (3)

Ra Ka
Ra Ka

Reputation: 3055

case class And(x:Any, y:Any)

def resolveAnd(lst: List[Int]):Any = {
  if (lst.isEmpty) throw new Exception("Invalid list provided.")
  lst.size match {
    case 1 => lst.head
    case _ => {
      val size = if(lst.size%2==0)lst.size else lst.size+1
      And(resolveAnd(lst.take(size/2)), resolveAnd(lst.drop(size/2)))
    }
  }
}

val list = 1::2::3::4::Nil
println(resolveAnd(list)) //output - And(And(1,2),And(3,4))

new Select(schema, resolveAnd(list))

Upvotes: 0

user267817
user267817

Reputation:

Assuming you want to build a tree hierarchy of And objects, you could use recursion to transform your list of Pat objects into a binary tree of nested And objects.

sealed abstract class Pat
case class Val(v: String) extends Pat
case class And(left: Pat, right: Pat) extends Pat

def buildParameterTree(xs: List[Pat]): Pat = {
  xs match {
    case p1 :: Nil => p1
    case p1 :: p2 :: Nil => And(p1, p2)
    case tail =>
      val halves = tail.splitAt(tail.length/2)
      And(buildParameterTree(halves._1), buildParameterTree(halves._2))
  }
}

Usage:

scala> buildParameterTree(List("p1").map(Val))
res1: Pat = Val(p1)
scala> buildParameterTree(List("p1", "p2").map(Val))
res2: Pat = And(Val(p1),Val(p2))
scala> buildParameterTree(List("p1", "p2", "p3").map(Val))
res3: Pat = And(Val(p1),And(Val(p2),Val(p3)))
scala> buildParameterTree(List("p1", "p2", "p3", "p4").map(Val))
res4: Pat = And(And(Val(p1),Val(p2)),And(Val(p3),Val(p4)))

And so on...

For more information about the match statement and recursion in Scala see the respective links.

Upvotes: 1

jwvh
jwvh

Reputation: 51271

So you are wanting to And() all the elements of the list? Would this work?

new Select(schema, list.reduce(And))

Upvotes: 1

Related Questions