我正在编写一个
Scala应用程序并尝试以功能方式迭代表(以二维数组的形式).对于表中的每一行,我想用第一列中的所有不同值填充Set,并使用第二列中的所有不同值填充第二个Set.
我尝试了很多方法,但找不到任何解决方法如何以功能方式进行.因为我从迭代中得到2个新变量,所以没有非功能性帮助似乎是不可能的.
这是一个非功能性示例,其中包含可变HashSets,用于包含产品和客户的表:
val myInputTable = Array(Array("Product A","Customer 1"),Array("Product B",Array("Product C","Customer 2"),Array("Product A","Customer 2")) val productSet = new collection.mutable.HashSet[String] val customerSet = new collection.mutable.HashSet[String] for( inputLine <- myInputTable; inputElement <- inputLine ) { if (inputLine.indexOf(inputElement) == 0) { productSet.add(inputElement) } else { customerSet.add(inputElement) } } println("Product Set:") productSet.foreach(println) println("\nCustomer Set:") customerSet.foreach(println)
有没有办法如何使用不可变集,其他对象或者for-yield语法来做到这一点?
感谢您的任何答案或提示,
费利克斯
解决方法
每当你发现自己尝试FP-ify迭代序列的代码同时更新一些可变状态时,一个好的第一种方法是使用foldLeft:
val myInputTable = Array(Array("Product A","Customer 2")) val (products,customers) = myInputTable.foldLeft((Set.empty[String],Set.empty[String])) { case ((ps,cs),Array(p,c)) => (ps + p,cs + c) case ((ps,_) => (ps,cs) // Alternatively fail here. }
foldLeft的第一个参数是初始状态.我们想使用两个不可变集,所以我们使用Set.empty [String]的元组. foldLeft的下一个参数是一个函数:
{ case ((ps,cs) // Alternatively fail here. }
这应该是从当前累积状态(ps,cs)和每个元素Array(p,c)到下一个状态的函数.它将从左到右应用于集合中的每个函数(因此foldLeft),累积状态更改,并返回状态的最终值.它的工作原理如下:
scala> val (products,customers) = | myInputTable.foldLeft((Set.empty[String],Set.empty[String])) { | case ((ps,cs + c) | case ((ps,cs) // Alternatively fail here. | } products: scala.collection.immutable.Set[String] = Set(Product A,Product B,Product C) customers: scala.collection.immutable.Set[String] = Set(Customer 1,Customer 2)
在某些情况下,可能会有更多特定的组合器允许您更简洁地表达您的操作,但foldLeft是一个很好的通用起点,允许从可变代码到纯功能代码的相当直接的转换.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。