如何将这个具有不可变成员的非功能scala代码转换为优雅的解决方案?

如何将这个具有不可变成员的非功能scala代码转换为优雅的解决方案?,scala,functional-programming,immutability,Scala,Functional Programming,Immutability,如何避免可变索引并使其更加优雅?我知道必须使用Option更改Null,我只是对答案感到好奇 class Person(val name: String, val department: String) var people = Array(new Person(“Jones”, “Marketing”), new Person(“Smith”, “Engineering”)) var engineer: Person = null var index = 0 while (index &l

如何避免可变索引并使其更加优雅?我知道必须使用Option更改Null,我只是对答案感到好奇

class Person(val name: String, val department: String)

var people = Array(new Person(“Jones”, “Marketing”), new Person(“Smith”, “Engineering”))
var engineer: Person = null
var index = 0

while (index < people.length) {

  if (people(index).department == “Engineering”) 
    engineer = people(index)

  index = index + 1


}
println(engineer.name + “ is an engineer”)
class-Person(val-name:String,val-department:String)
var people=Array(新人(“琼斯”、“营销”)、新人(“史密斯”、“工程”))
变量工程师:Person=null
var指数=0
while(指数<人长){
if(人员(索引)。部门==“工程”)
工程师=人员(索引)
索引=索引+1
}
println(engineer.name+“是工程师”)

以下是我重构的方法:

// Refactored into a case class, since it's a simple data container
case class Person(name: String, department: String)

// Using the case class convenience apply method to drop `new` 
val people = Array(Person(“Jones”, “Marketing”), Person(“Smith”, “Engineering”))

// Selects all the engineers. You could add `.headOption` to get the first. 
val engineers = people.filter(_.department == "Engineering")

// Functional way of iterating the collection of engineers
// Also, using string interpolation to print
for (engineer <- engineers) println(s"${engineer.name} is an engineer.")

最后一个提示,如果你的部门是固定的选项的有限集合,你也应该考虑把它变成一个类型:

sealed trait Department
case object Engineering extends Department
case object Marketing extends Department
// ... for each valid department

然后你可以根据身份而不是价值来匹配。这使您可以依赖类型系统,而不必经常验证字符串(有些人称为)。最佳做法是尽早将数据验证为类型,将其作为类型化数据处理,然后仅转换回字符串,以便将数据从系统中导出(例如,打印到屏幕、记录、通过API提供服务)。

您可以使用
查找
首先查找:

people
  .find { _.department == "Engineering" }
  .foreach { engineer => println(engineer.name + " is an engineer") }
过滤器
查找所有:

people
  .filter { _.department == "Engineering" }
  .foreach { engineer => println(engineer.name + " is an engineer") }
顺便说一下,只需将增量操作移到
if
块之外,就可以修复代码:

if (people(index).department == "Engineering") {
  engineer = people(index)
  // index = index + 1
}
index = index + 1
之后,您应该检查
engineer
中的
null
,因为您的数组可能不包含符合您的条件的
人员

因此,您似乎希望找到最后一个
,因此您可以使用:

people
  .foldLeft(None: Option[Person])((r, p) =>
    if (p.department == "Engineering") Some(p) else r)
  .foreach { engineer => println(engineer.name + " is an engineer") }

另外,在避免所有
var
之后,您还可以将
数组
(可变结构)更改为
列表
(默认为scala.collection.immutable.List)

如果您想找到数组中的最后一个工程师,您可能会使用:

case class Person(val name: String, val department: String)

val people = Array(Person(“Jones”, “Marketing”), Person(“Smith”, “Engineering”))

def findLastEngineer(l: Seq[Person]) : Option[Person] =  
  people.foldLeft(None) { 
    case (previousOpt, eng) => if (eng.department == "Engineering") Some(eng) else previousOpt
  }
}

println(findLastEngineer(people).map(_.name).getOrElse("Not found"))

我会这样做:

case class Person(name: String, department: String)

val people = List(Person("Jones", "Marketing"), Person("Smith", "Engineering"))

val engineers = people.filter { person:Person => person.department == "Engineering" }

engineers.map { engineer: Person => println(engineer.name + " is an engineer") }

尝试使用函数转换其他类型中的类型。通常我们使用map/reduce/filter函数来实现这一点。

此代码包含bug(无限循环)。你想在功能代码中得到这个bug吗?如果你能用文字描述代码片段实际应该做什么,也许会有帮助。所以你想打印列表名称上的最后一个工程师?或者任何?或者首先?这不是一个真正的问题:这是从StackOverflowCareers上的招聘广告中剪下来粘贴的:也许OP应该遵循他们的建议:“如果你必须用谷歌搜索任何东西来做这件事,那么现在可能不是你申请的合适时机。”谁在乎申请呢?谢谢你,这很有启发性和解释性。顺便说一句,工程设计后缺少双引号。对,函数map/reduce/filter已经处理集合中的所有元素,因此我们不必麻烦使用可变索引,只需
people.filter(Person.department.equals(“工程”)。last
case class Person(val name: String, val department: String)

val people = Array(Person(“Jones”, “Marketing”), Person(“Smith”, “Engineering”))

def findLastEngineer(l: Seq[Person]) : Option[Person] =  
  people.foldLeft(None) { 
    case (previousOpt, eng) => if (eng.department == "Engineering") Some(eng) else previousOpt
  }
}

println(findLastEngineer(people).map(_.name).getOrElse("Not found"))
case class Person(name: String, department: String)

val people = List(Person("Jones", "Marketing"), Person("Smith", "Engineering"))

val engineers = people.filter { person:Person => person.department == "Engineering" }

engineers.map { engineer: Person => println(engineer.name + " is an engineer") }