Scala:递归地修改元素/列表的列表

|| 我希望有人可以在Scala中为我提供一些基本的代码帮助。我已经用Python编写了一些演示代码。 考虑一个元素列表,其中一个元素可以容纳整数或其他元素列表。我想递归检查此结构并在保留整个结构的同时对其进行修改。 为了用python表示这一点,我将每个\\\\\\\\\\\\\\\\\\\\的组成了一键字典(item为\'i \')。对应于该键的值是int或类似字典的列表。从而,
lst = [{\'i\': 1}, {\'i\': 2}, {\'i\': [{\'i\': 5}, {\'i\': 6}]}, {\'i\': 3}]

def recurse(x):
  if isinstance(x, list):
    return [recurse(a) for a in x]
  else:
    if isinstance(x[\'i\'], list):
      return dict(i=[recurse(a) for a in x[\'i\']])
    else:
      return dict(i=(x[\'i\'] + 1))

print \"Input:\"
for i in lst:
    print i
print \"\\nResult:\\n%s\" % recurse(lst)

>>>
Input:
{\'i\': 1}
{\'i\': 2}
{\'i\': [{\'i\': 5}, {\'i\': 6}]}
{\'i\': 3}

Result:    
[{\'i\': 2}, {\'i\': 3}, {\'i\': [{\'i\': 6}, {\'i\': 7}]}, {\'i\': 4}]
我知道这是做事的一种怪异方法,但是我提供的数据就是这样构造的。我认为我的问题是python允许您从同一函数返回不同类型,而我不认为Scala可以。 同样为了记录,Scala元素表示为Elem(4)或Elem(List(Elem(3)...),因此我认为可以在其中进行模式匹配。     
已邀请:
        我不想将其称为“列表列表”,因为它不能告诉您这些列表包含哪些内容。该结构是一棵树,更确切地说是一棵多叶的树,其中仅在叶子中存在数据。那将是:
sealed trait Tree[+A]
case class Node[+A](children: Tree[A]*) extends Tree[A]
case class Leaf[+A](value: A) extends Tree[A]
然后添加方法映射以将函数应用于树中的每个值
sealed trait Tree[+A] {
  def map[B](f: A => B): Tree[B]
}
case class Node[+A](children: Tree[A]*) extends Tree[A] {
  def map[B](f : A => B) = Node(children.map(_.map(f)): _*)
}
case class Leaf[+A](value: A) extends Tree[A] {
  def map[B](f: A => B) = Leaf(f(value))
}
那么您的输入是:
val input = Node(Leaf(1), Leaf(2), Node(Leaf(5), Leaf(6)), Leaf(3))
如果您呼叫
input.map(_ + 1)
,您将得到输出 由于varargs Tree [A] *,结果显示有些难看。您可以通过添加节点ѭ5来改善 您可能只喜欢在类外部或直接在Tree中的某个位置使用该方法。这是Tree中的一种方法
def map[B](f: A => B): Tree[B] = this match {
  case Node(children @ _*) => Node(children.map(_.map(f)): _*)
  case Leaf(v) => Leaf(f(v))
}
像在Python中那样使用无类型的方式并不是很容易,但是可以完成。
def recurse(x: Any) : Any = x match {
  case list : List[_] => list.map(recurse(_))
  case value : Int => value + 1
}
(将值直接放在列表中。带有键“ i”的地图(字典)使其复杂化并强制接受编译器警告,因为我们将不得不强制执行无法检查的强制转换,即,地图接受字符串作为键:案例映射:Map [String,_]) 与直接将值直接放入List相比,使用
case Elem(content: Any)
听起来没有任何额外的安全性,同时更为冗长,并且将其称为树并区分节点和叶子而不明显地麻烦也没有安全性和清晰度。     
        好吧,这是可行的,但是有点难看:
def make(o: Any) = Map(\'i\' -> o) // m :: Any => Map[Char,Any]
val lst = List(make(1),make(2),make(List(make(5),make(6))),make(3)) // List[Any]

def recurce(x: Any): Any = x match {
  case l: List[_] => l map recurce
  case m: Map[Char,_] => val a = m(\'i\')
    a match {
      case n: Int => make(n + 1)
      case l: List[_] => make(l map recurce)
    }
}
范例:
scala> recurce(lst)
res9: Any = List(Map((i,2)), Map((i,3)), Map((i,List(Map(i -> 6), Map(i -> 7)))), Map((i,4)))
    
        此解决方案更安全,但不必求助于树(这不是一个坏解决方案,但是已经有人做到了:)。这将是一个int或int列表。因此,它只能有两个级别-如果需要更多级别,请制作一棵树。
val lst = List(Left(1), Left(2), Right(List(5, 6)), Left(3))

def recurse(lst: List[Either[Int, List[Int]]]): List[Either[Int, List[Int]]] = lst match {
    case Nil => Nil
    case Left(n) :: tail => Left(n + 1) :: recurse(tail)
    case Right(l) :: tail => Right(l map (_ + 1)) :: recurse(tail)
}
    

要回复问题请先登录注册