2

我还在学习斯卡拉。如果我有一句话

val word = "abcd"

我想创建

Map("bcd","acd","abd","abc")

到目前为止,我尝试过:

  println(word.map(word.split(_).foldLeft("")(_+_)))

但如果我在单词中重复了字符,它就会失败。

请帮忙。

4

5 回答 5

8

它不一定是最有效的方法,但是您可以使用initsandtails方法非常干净地做到这一点,而无需处理可以说“功能较少”的索引:

scala> val word = "abcd"
word: String = abcd

scala> (word.inits.toList.tail.reverse zip word.tails.toList.tail).map {
     |   case (x, y) => x + y
     | }
res0: List[String] = List(bcd, acd, abd, abc)

它将按预期使用重复项。

要了解它是如何工作的,请考虑以下几点:

scala> word.inits foreach println
abcd
abc
ab
a


scala> word.tails foreach println
abcd
bcd
cd
d

从那里只需将两者结合在一起即可获得所需的结果。


下面是一个更高级的解决方案,它使用Scalaz库的 zippers 实现它提供了一种非常干净的方法来解决这个问题:

import scalaz._, Scalaz._

"abcd".toList.toZipper.map(
  _.cobind(z => (z.lefts.reverse ++ z.rights).mkString).toList
)

这将返回Some(List(bcd, acd, abd, abc)),其中可选的包装器表示空拉链没有意义的事实。实际上,您可能希望以相同的方式对解决方案进行建模(如果您打算使其更通用),因为从空字符串中“省略一个”也没有意义。

如果您不在乎,只想让空字符串生成一个空列表,您可以getOrElse Nil在此处附加。

于 2013-09-15T17:44:48.167 回答
4
scala> def foo(str:String)=(0 until str.length).map(i=>str.substring(0,i)+str.substring(i+1))
foo: (str: String)scala.collection.immutable.IndexedSeq[String]

scala> foo("abcd")
res28: scala.collection.immutable.IndexedSeq[String] = Vector(bcd, acd, abd, abc)
于 2013-09-15T16:14:27.187 回答
1

最简单的方法是使用 Scala 在 String 对象上提供的附加方法:

val word = "abcd"
word.combinations(3).toList

或者,如果您想删除重复字符:

word.distinct.combinations(3).toList

评论后更新 如果您想删除重复项,请使用我上面给出的第二个示例。为了您的示例完全准确:

val word = "abca"
word.distinct.combinations(word.distinct.length-1).toList

这返回

  res3: List[String] = List(ab, ac, bc)
于 2013-09-15T16:24:20.770 回答
1

收藏图书馆是寻找这些东西的最佳场所:

 def characterCombinations(word: String) = word
   .distinct.combinations(word.distinct.length - 1).toList
 characterCombinations("abcdaaaaaa") // outputs List(abc, abd, acd, bcd)

该词可隐式转换为IndexedSeq[Char]具有常用集合方法的 an ——distinct删除集合中的重复项,combinations(n)迭代集合中的n长度组合,length为您提供集合的长度,并将toList转换Iterator[String]List[String].

于 2013-09-15T19:04:42.530 回答
0

这是另一个解决方案:

val word = "abcd" 
(0 to 3) map (i => word.split(word(i)).foldLeft("")(_+_))
于 2013-09-16T17:21:14.883 回答