什么是Scala查找数组中所有元素是否具有相同长度的方法?

什么是Scala查找数组中所有元素是否具有相同长度的方法?,scala,functional-programming,Scala,Functional Programming,我是Scala新手,但对Java非常熟悉,对使用FP语言如“Haskell”有一定的了解 在这里,我想知道如何使用Scala实现这一点。数组中有一个元素列表,所有元素都是字符串,我只想知道是否有一种方法可以在Scala中以FP方式实现这一点。这是我目前的版本,它可以工作 def checkLength(vals: Array[String]): Boolean = { var len = -1 for(x <- conts){ if(len < 0) le

我是Scala新手,但对Java非常熟悉,对使用FP语言如“Haskell”有一定的了解

在这里,我想知道如何使用Scala实现这一点。数组中有一个元素列表,所有元素都是字符串,我只想知道是否有一种方法可以在Scala中以FP方式实现这一点。这是我目前的版本,它可以工作

def checkLength(vals: Array[String]): Boolean = {
  var len = -1
  for(x <- conts){
    if(len < 0)
      len = x.length()
    else{
      if (x.length() != len)
        return false
      else
        len = x.length()
    }
  }
  return true;
}
def checkLength(vals:Array[String]):布尔={
变量len=-1

对于(x提示:使用
forall
确定集合中的所有元素是否满足某个谓词(例如长度相等)

编辑:这是一个尽可能通用的定义,还允许检查除长度以外的属性是否对所有元素都相同:

def allElementsTheSame[T,U](f: T => U)(list: Seq[T]) = {
    val first: Option[U] = list.headOption.map( f(_) )
    list.forall( f(_) == first.get ) //safe to use get here!
}

type HasSize = { val size: Int }
val checkLength = allElementsTheSame((x: HasSize) => x.size)_

checkLength(Array( "123", "456") )

checkLength(List( List(1,2), List(3,4) ))

如果你知道你的列表总是非空的,那么一个直接的forall很好用。如果你不知道,很容易添加到:

list match {
  case x :: rest => rest forall (_.size == x.size)
  case _ => true
}

现在,长度为零的列表返回true,而不是抛出异常。

下面是另一种方法:

def check(list:List[String]) = list.foldLeft(true)(_ && list.head.length == _.length)

既然每个人看起来都很有创意,我也会很有创意。:-)

def checkLength(vals:Array[String]):Boolean=vals.map(u.length)。removeDuplicates.size仅我的0.02欧元

def allElementsEval[T, U](f: T => U)(xs: Iterable[T]) =
  if (xs.isEmpty) true
  else {
    val first = f(xs.head)
    xs forall { f(_) == first }
  }
这适用于任何
Iterable
,计算的次数尽可能少,并且当块不能被转换时,类型推断器可以推断块参数类型

  "allElementsEval" should "return true for an empty Iterable" in {
    allElementsEval(List[String]()){ x => x.size } should be (true)
  }
  it should "eval the function at each item" in {
    allElementsEval(List("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(List("aa", "bb", "ccc")) { x => x.size } should be (false)
  }
  it should "work on Vector and Array as well" in {
    allElementsEval(Vector("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(Vector("aa", "bb", "ccc")) { x => x.size } should be (false)
    allElementsEval(Array("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(Array("aa", "bb", "ccc")) { x => x.size } should be (false)
  }
对于Iterables来说,
head::tail
模式匹配如此阴险地失败,这只是一个遗憾

list.groupBy{_.length}.size == 1
您可以将列表转换为等长字符串组的映射。如果所有字符串的长度相同,则映射将只包含一个这样的组


这个解决方案的好处是,你不需要知道任何关于字符串长度的信息,也不需要将它们压缩到第一个字符串。它在空字符串上工作得很好,在这种情况下,它返回false(如果这是你想要的话)

+1是的。后一个术语甚至不能是
list forall(uu.size==list(0)吗.size)
?非常好。经过一些尝试后,我最终完成了以下操作…
def checkLenght(vals:Array[String]):Boolean=vals.forall(u.length==vals(0.length)
@Teja Kantamneni:请注意,如果不检查大小,则将该方法应用于空数组时会出现错误。还请注意,如果将VAL声明为
Seq[String]
而不是
Array[String]
,则它也适用于列表等,而不仅仅是数组。(您还可以将其推广到处理任何具有长度方法的序列,而不仅仅是字符串)@sepp2k:好吧,它不应该抛出任何错误,因为只有在有元素的情况下你才会进入循环。事实上,我对Scala world非常陌生,上周末才开始学习。我非常感谢你的帮助。@oxbow_lakes,我不确定我是否同意帮助函数是不必要的。这一点很明显(从名称上看)helper函数在做什么。至少对于像我这样的凡人来说,了解代码是如何做的并不是那么快。有一个“思考,思考,啊,这就是它正在检查的”过程——还有一个不那么琐碎的情况,这增加了很多不必要的思考时间。我认为Kent Beck的一些smalltalk模式,比如“分解消息”当翻译成Scala时,“意图揭示方法”同样适用……这是相当非典型的,您的13行Java(基本上是您用Scala语法编写的Java)可以减少为1行scala。1行scala的可读性、可理解性和可维护性都大大提高了!我说非典型,通常只能将13行Java压缩为2行scala!阵列上是否可以进行模式匹配?@Dario-是的,它们与序列匹配。这种行为在2.8中略有改变,但它们仍然可以我可以用在图案中-matching@Dario-是的。如果“list”是一个数组,请改用
大小写数组(x,rest@*)=>
。这在2.7和2.8.0中都有效。聪明!但在重命名它之前,
(Set()++list.map(u.length))。大小
对于所有
方法更有效。
  "allElementsEval" should "return true for an empty Iterable" in {
    allElementsEval(List[String]()){ x => x.size } should be (true)
  }
  it should "eval the function at each item" in {
    allElementsEval(List("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(List("aa", "bb", "ccc")) { x => x.size } should be (false)
  }
  it should "work on Vector and Array as well" in {
    allElementsEval(Vector("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(Vector("aa", "bb", "ccc")) { x => x.size } should be (false)
    allElementsEval(Array("aa", "bb", "cc")) { x => x.size } should be (true)
    allElementsEval(Array("aa", "bb", "ccc")) { x => x.size } should be (false)
  }
list.groupBy{_.length}.size == 1