从Scala数组中提取区域

fbl*_*fbl 4 algorithm functional-programming scala partitioning

我真的不知道如何描述我在做什么,但这个例子应该有所帮助:

val vals = Array( (0, true), 
                  (1, true), 
                  (2,true), 
                  (3,true), 
                  (4,false), 
                  (5, true), 
                  (6, true), 
                  (7, false), 
                  (8, true), 
                  (9,true))
Run Code Online (Sandbox Code Playgroud)

我希望识别每个"真实"区域中的第一个和最后一个元素,尽管在值更改时对数组进行分区也可以正常工作.我可以强制执行此操作,但在scala中执行此操作的最佳方法是什么?

huy*_*hjl 5

如果您不介意添加一些基础设施来处理groupedWhile功能,您可以从Rex Kerr的扩展scala集合答案中窃取.在答案的第二部分中使用处理数组的部分.

然后这是一件轻而易举的事:

scala> vals.groupedWhile(_._2 == _._2).filter(_.head._2 == true).map{g => 
  (g.head, g.last)}.foreach(println)

((0,true),(3,true))
((5,true),(6,true))
((8,true),(9,true))
Run Code Online (Sandbox Code Playgroud)

编辑:

我提出了一个不需要的解决方案groupedWhile.它基于使用Iterator.iterate从种子开始并重复应用该span函数来提取具有相同布尔属性的下一组元素.在这种情况下,种子是下一组的元组,其余部分用于处理:

type Arr = Array[(Int, Boolean)] // type alias for easier reading

val res = Iterator.iterate[(Arr, Arr)]((Array(), vals)){ case (same, rest) => 
  // repeatedly split in (same by boolean, rest of data)
  // by using span and comparing against head
  rest.span(elem => elem._2 == rest.head._2)
}.drop(1).takeWhile{ case (same, _) =>        // drop initial empty seed array
  same.nonEmpty                               // stop when same becomes empty
}.collect{ case (same, _) if same.head._2 == true =>
  // keep "true" groups and extract (first, last)
  (same.head, same.last)                     
}.foreach(println)                            // print result
Run Code Online (Sandbox Code Playgroud)

其打印结果与上述相同.请注意,span对于空数组不会调用谓词,因此rest.head如果rest为空,则不会出现异常.