scala 过滤字符串,删除与同一索引中的另一个字符串具有相同元素的所有元素

dbf7pr2w  于 2023-01-20  发布在  Scala
关注(0)|答案(1)|浏览(133)

正如title所说,我想实现一个函数,pool,它在移除给定字符串中与另一个字符串在相同索引中相同字母的所有元素后,返回一个字符列表。它给了我一个StringIndexOutOfBoundsExceptions,这是由于我编写了代码来获取给定索引中的元素。我该如何解决这个问题?
我的实现

def pool(secret: String, word: String) : List[Char] = { 
    secret.filterNot(x => secret.apply(x) == word.apply(x)).toList
}

测试用例

pool("chess", "caves") => List(h, e, s)
pool("chess", "swiss") => List(c, h, e)

错误信息

java.lang.StringIndexOutOfBoundsException: String index out of range: 99
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)
at java.base/java.lang.String.charAt(String.java:1515)
at scala.collection.StringOps$.apply$extension(StringOps.scala:188)
at $anonfun$pool$1(<console>:3)
at $anonfun$pool$1$adapted(<console>:3)
at scala.collection.StringOps$.filterNot$extension(StringOps.scala:1264)
at pool(<console>:3)
... 32 elided
y0u0uwnf

y0u0uwnf1#

x是一个 * 字符 *,String.apply接受一个 * 索引 *。c有一个acii代码99,所以当你执行"caves".apply('c')时,它试图访问“caves”中索引为99的字符,并抛出,因为字符串不够长。
如果您坚持使用实际的索引,那么类似下面的代码可能会起作用:

secret.zipWithIndex.collect { case (c, i) if word(i) != c => c }.mkString

但是,如果word恰好比secret短,则仍然会抛出。如果愿意,可以添加另一个条件来防止这种情况(case (c,i) if i >= word.length || word(i) != c => c),但是类似于这样的东西会更有可读性和惯用性(直接索引访问在Scala中通常不受欢迎,因为它经常会导致微妙的性能问题,并且导致读取器花费额外的周期以便证明其在给定情况下是合法的):

secret
  .iterator
  .zipAll(word, 0.toChar, 0.toChar)
  .collect { case (a,b) if a != b && a != 0.toChar => a }
  .mkString

相关问题