返回特定子字符串的所有索引

时间:2014-07-21 20:57:06

标签: string scala indexof

是否有Scala库API方法(如果不是,这是一种惯用的方法)来获取更大字符串(源)中子字符串(目标)的所有索引的列表?我试图浏览ScalaDoc,但无法找到任何明显的东西。有很多方法可以做很多有用的事情,我猜我只是没有提交正确的搜索词。

例如,如果我的源字符串为“name:Yo,name:Jim,name:name,name:bozo”,我使用目标字符串“name:”,我想找回一个List列表的[Int](0,8,17,27)。

这是我快速解决问题的方法:

def indexesOf(source: String, target: String, index: Int = 0, withinOverlaps: Boolean = false): List[Int] = {
    def recursive(index: Int, accumulator: List[Int]): List[Int] = {
      if (!(index < source.size)) accumulator
      else {
        val position = source.indexOf(target, index)
        if (position == -1) accumulator
        else {
          recursive(position + (if (withinOverlaps) 1 else target.size), position :: accumulator)
        }
      }
    }

    if (target.size <= source.size) {
      if (!source.equals(target)) {
        recursive(0, Nil).reverse
      }
      else List(0)
    }
    else Nil
  }

任何指导都可以让我用适当的标准库入口点替换它,我们将不胜感激。

更新2014 / Jul / 22:

受Siddhartha Dutta的回答启发,我加强了我的代码。它现在看起来像这样:

  def indexesOf(source: String, target: String, index: Int = 0, withinOverlaps: Boolean = false): List[Int] = {
    @tailrec def recursive(indexTarget: Int, accumulator: List[Int]): List[Int] = {
      val position = source.indexOf(target, indexTarget)
      if (position == -1) accumulator
      else
        recursive(position + (if (withinOverlaps) 1 else target.size), position :: accumulator)
    }
    recursive(index, Nil).reverse
  }

另外,如果我有一个源代码字符串“aaaaaaaa”并使用目标字符串“aa”,我希望默认情况下返回List的列表[Int](0,2,4,6)从已找到的子字符串开始跳过搜索。默认值可以通过为“aaaaaaa”/“aa”情况下返回List(0,1,2,3,4,5,6)的withinOverlaps参数传递“true”来覆盖。

2 个答案:

答案 0 :(得分:6)

我总是倾向于接触到像这样的问题的正则表达式技巧。我不会说它是正确的,但这是一个很少的代码。 :)

val r = "\\Qname\\E".r
val ex = "name:Yo,name:Jim,name:name,name:bozo"

val is = r.findAllMatchIn(ex).map(_.start).toList

对于这种情况,引号\\Q\\E不是必需的,但如果您要查找的字符串有任何特殊字符,那么它就是。

答案 1 :(得分:1)

获取所有索引的小代码
将以下方法称为getAllIndexes(source,target)

def getAllIndexes(source: String, target: String, index: Int = 0): List[Int] = {
        val targetIndex = source.indexOf(target, index)
        if(targetIndex != -1)
          List(targetIndex) ++ getAllIndexes(source, target, targetIndex+1)
        else
          List()
      }