2014-07-21 1 views
6

큰 문자열 (소스) 내의 하위 문자열 (대상)에 대한 모든 인덱스 목록을 얻으려면 스칼라 라이브러리 API 방법이 있습니까 (아니라면 관용적 방법)? ScalaDoc을 살펴 보려고했지만 명백한 것을 찾을 수 없었습니다. 너무 많은 유용한 것들을하는 많은 방법이 있습니다. 나는 정확한 검색 용어를 제출하지 않고 있다고 생각합니다.특정 하위 문자열의 모든 인덱스를 반환합니다.

예를 들어 "name : Yo, name : Jim, name : name, name : bozo"라는 소스 문자열이 있고 "name :"이라는 대상 문자열을 사용하고 싶습니다. 목록의 [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 
    } 

모든 지침 당신이 날 주시면 감사하겠습니다 적절한 표준 라이브러리 진입 점과이 대체 제공 할 수 있습니다 :

다음은 문제를 해결하기 위해 내 빠른 해킹.

는 UPDATE 2014/7월/22 : 싯다르타 두타의 대답에 영감을

, 내 코드를 tighted. 지금은 다음과 같습니다

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"의 대상 문자열을 사용하는 경우, 내가 다시 목록 [지능]의 얻기 위해 기본적으로 싶습니다 발견 된 부분 문자열 내에서 검색을 건너 뛰는 목록 (0, 2, 4, 6). "aaaaaaaa"/ "aa"경우 List (0, 1, 2, 3, 4, 5, 6)를 반환하는 withinOverlaps 매개 변수에 "true"를 전달하여 기본값을 재정의 할 수 있습니다.

+1

아니오, "는 [표준] 방법"이없는을 얻을 수 있습니다. 또한이 코드는 작동중인 코드이므로 코드 검토에 더 적합 할 수도 있습니다. – user2864740

+0

@ chaotic3quilibrium 어떤 방법 으로든 BSD 라이센스로 그 방법을 사용하면 사장님이 복사/수정하면 저에게 화를 내지 않으실 겁니다. :) – ericpeters

+0

@ericpeters StackOverflow에 게시 된 코드 스 니펫은 본질적으로 공개 도메인이라고 가정 할 수 있습니다. 즉, 필요한 모든 컨텍스트로 스 니펫을 잘라내거나 붙여 넣거나 수정하거나 사용자 정의 할 수있는 능력을 제한하는 라이센스 제한으로 인해 제약을받지 않습니다. – chaotic3quilibrium

답변

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이 경우에 필요하지 않습니다,하지만 당신이 찾고있는 문자열에 특수 문자가있는 경우, 다음이 될 것입니다.

+0

아주 좋네요. 나는 내 코드 Scala를 채우기 전에 정규 표현식 접근법을 평가하는 데 2 ​​분 미만을 보냈다. 문자열 검색 고양이를 스킨하는 방법은 여러 가지가 있습니다. – chaotic3quilibrium

+0

BTW에서는 순수 정규식 (다른 원본의 이스케이프되지 않은 복사/붙여 넣기)을 사용하려는 경우 첫 줄을 "" "\"Qname \ E "". r으로 변경할 수도 있습니다. 스칼라의 삼중 따옴표 옵션은 멋지다! – chaotic3quilibrium

1

작은 코드는 모든 인덱스
전화 getAllIndexes로 아래의 방법 (소스, 목표)

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() 
     } 
+0

목록이 역순으로 반환됩니다 (List (27, 17, 8, 0))? 또한 경로를 두 경우 최적화 할 수 있습니다. 첫 번째 "List (targetIndex) ++ get ..."을 "targetIndex :: get ..."으로 바꿉니다. 두 번째는 "List()"를 "Nil"로 대체합니다. – chaotic3quilibrium

+1

아니요 메서드는 인덱스 (예 : List (0,8,17,27))에 따라 오름차순으로 목록을 반환합니다. 최적화가 정확합니다. –

+0

방금 ​​호출을 시도하고 @tailrec 주석을 추가 한 후 ++ 또는 :와 함께 꼬리 재귀가 아니라는 컴파일러 오류가 발생합니다. 그러나, 당신의 작은 코드는 저에게 영감을주었습니다. 그래서 제 코드가 강화되었음을 보여주는 업데이트를 제공했습니다. 선택적인 withinOverlaps 매개 변수의 이점을 보여주기 위해 또 다른 테스트 케이스 ("aaaaaaaa", "aa"예제)를 추가했습니다. – chaotic3quilibrium