使用纯函数中的var来处理scala代码.这可能没有变量吗?

Fra*_*ner 0 functional-programming scala

是否有可能(甚至值得)尝试在没有var的情况下编写下面的代码块?它适用于var.这不是面试,这是我第一次尝试scala(来自java).

问题是:让人们尽可能靠近剧院前面,同时将每个请求(例如,琼斯,4张票)保存在一个剧院区域.剧院部分从正面开始,大小分别为6,6,3,5,5 ......等等.我试图通过将所有潜在的票证请求组合在一起,然后为每个部分选择最合适的组来实现这一目标.

这是课程.SeatingCombination是SeatingRequest(只是ID)和ticketCount(s)之和的一种可能组合:

class SeatingCombination(val idList: List[Int], val seatCount: Int){}
class SeatingRequest(val id: Int, val partyName: String, val ticketCount: Int){}
class TheatreSection(val sectionSize: Int, rowNumber: Int, sectionNumber: Int) {
  def id: String = rowNumber.toString + "_"+ sectionNumber.toString;
}
Run Code Online (Sandbox Code Playgroud)

当我们到达下面的函数时...... 1.)SeatingRequest的所有可能组合都在SeatingCombination列表中,并按降序排序.2.)按顺序列出所有TheatreSection.

def getSeatingMap(groups: List[SeatingCombination], sections: List[TheatreSection]): HashMap[Int, TheatreSection] = {
    var seatedMap = new HashMap[Int, TheatreSection]
    for (sect <- sections) {
      val bestFitOpt = groups.find(g => { g.seatCount <= sect.sectionSize && !isAnyListIdInMap(seatedMap, g.idList) })
      bestFitOpt.filter(_.idList.size > 0).foreach(_.idList.foreach(seatedMap.update(_, sect)))
    }
    seatedMap 
}

def isAnyListIdInMap(map: HashMap[Int, TheatreSection], list: List[Int]): Boolean = {
    (for (id <- list) yield !map.get(id).isEmpty).reduce(_ || _)
  }
Run Code Online (Sandbox Code Playgroud)

我在没有var的情况下编写了程序的其余部分,但在这个迭代部分中似乎不可能.也许我的实施策略是不可能的.从我读过的其他内容来看,纯函数中的var仍然有效.但它一直在困扰我,我无法想到如何删除var,因为我的教科书告诉我试图避免它们,我不知道我不知道的.

Cyr*_*pet 5

您可以使用foldLeft迭代sections运行状态(再次,在内部,在您的状态上迭代地添加一个部分中的所有ID):

sections.foldLeft(Map.empty[Int, TheatreSection]){
  case (seatedMap, sect) =>
    val bestFitOpt = groups.find(g => g.seatCount <= sect.sectionSize && !isAnyListIdInMap(seatedMap, g.idList))
    bestFitOpt.
      filter(_.idList.size > 0).toList.  //convert option to list
      flatMap(_.idList). // flatten list from option and idList
      foldLeft(seatedMap)(_ + (_ -> sect))) // add all ids to the map with sect as value
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您可以使用exists和简化第二种方法map.contains:

def isAnyListIdInMap(map: HashMap[Int, TheatreSection], list: List[Int]): Boolean = {
list.exists(id => map.contains(id))
Run Code Online (Sandbox Code Playgroud)

}

list.exists(predicate: Int => Boolean)是一个布尔值,如果谓词对于任何元素为真,则为true list.

map.contains(key)检查是否map定义为key.

如果您想要更简洁,则不需要为谓词的参数指定名称:

list.exists(map.contains)
Run Code Online (Sandbox Code Playgroud)