Scala将一个集合类型变量初始化为for循环外的null,并将一些方法的返回值赋给循环内的变量

时间:2014-04-28 10:35:40

标签: scala scala-collections for-comprehension

我是使用Scala的新手。

我有一个Scala Vector包含Person个对象,我需要在其上循环并将Vector的每个元素传递给方法personCollector,其返回值也是Vector。从for循环下面的Scala REPL输出中可以看出,它打印了由personCollector返回的Vector三次,这是因为people Vector包含三个条目。但是我想要打印personCollector返回的向量只有一次,即for循环迭代结束后。

在Java中我可以按照以下方式执行:

var peopleWithFirstName = null;
for (Person p :  people)
  peopleWithFirstName = firstNameCollector(p);

System.out.println(peopleWithFirstName);

但是我无法想象在Scala中执行上述操作.Below是我的Scala代码。

    Welcome to Scala version 2.10.4 (Java HotSpot(TM) Server VM, Java 1.7.0_04).
    Type in expressions to have them evaluated.
    Type :help for more information.

    scala>   case class Person(
         |       firstName: Option[String],
         |       middleName: Option[String],
         |       lastName: Option[String] )
    defined class Person

    scala> def isFirstNameValid(person: Person) = person.firstName.isDefined
    isFirstNameValid: (person: Person)Boolean

    scala>   def personCollector(isValid: (Person) => Boolean) = {
         |     var validPeople = Vector[Person]()
         |     (person: Person) => {
         |       if(isValid(person)) validPeople = validPeople :+ person
         |       validPeople
         |     }
         |   }
    personCollector: (isValid: Person => Boolean)Person => scala.collection.immutable.Vector[Person]

    scala> val p1 = Person(Some("First Name"), Some("Middle Name"), Some("Last Name"))
    p1: Person = Person(Some(First Name),Some(Middle Name),Some(Last Name))

    scala> val p2 = Person(None, Some("Middle Name"), None)
    p2: Person = Person(None,Some(Middle Name),None)

    scala> val p3 = Person(Some("First Name"), None, None)
    p3: Person = Person(Some(First Name),None,None)

    scala> val people = Vector(p1, p2, p3)
    people: scala.collection.immutable.Vector[Person] = Vector(Person(Some(First Name),Some(Middle Name),Some(Last Name)), Person(None,Some(Middle Name),None), Person(Some(First Name),None,None))

    scala> val firstNameCollector = personCollector(isFirstNameValid)
    firstNameCollector: Person => scala.collection.immutable.Vector[Person] = <function1>

    scala> for (p <- people)
         | println(firstNameCollector(p))
    Vector(Person(Some(First Name),Some(Middle Name),Some(Last Name)))
    Vector(Person(Some(First Name),Some(Middle Name),Some(Last Name)))
    Vector(Person(Some(First Name),Some(Middle Name),Some(Last Name)), Person(Some(First Name),None,None))

感谢。

1 个答案:

答案 0 :(得分:2)

我不完全确定你的实际目标是什么。我猜你想要实现的目标似乎可以通过filtermap更好地解决:

    在这种情况下,
  • filter充当验证者,即people.filter(isFirstNameValid)。这将返回具有已定义名字的所有人的集合 - 这是您想要的吗?
  • map用作所需字段的提取器,在本例中为名字。总体而言people.filter(isFirstNameValid).map(_.firstName),以防您希望您的收藏品代表名字而不是完整的人。如果您还希望将Option(名字)转换为具体值,则可能需要使用flatMap(这也使得不需要显式验证)。

如果您真的想要坚持基于修改外部状态的解决方案,您必须将可变变量放在外部范围中,例如......