2

어떻게이 프로그래밍 로직을 함수 메쏘드 서명에 쓸 수 있습니까? 조건이 충족 될 때까지 배열을 반복/통과하려고 시도하고 그 조건을 위반합니다. 대부분 varbreakablescala.util.control.Breaks에서 피하기 위해 최선을 다하고 있습니다. 조건/술어가 충족되는지 확인하기 위해 클로저 (이 경우 dictionary)를 사용합니다. 아이디어는 술어가 만날 때까지 배열을 반복하고 있다는 것입니다. 또한 배열을 목록으로 변환하는 것을 피합니다. 배열을 사용하면 배열을 이어 붙일 수 없습니다. 예를 들어, 패턴 일치를 할 수 있습니까? 여기 var 또는 breakable 없음 : 배열 탐색에서 조건자가 충족 될 때 "중단"하는 방법?

val dictionary = Array.fill(128)(false) 

def isUnique(array: Array[Char]): Option[Char] = { 

    // traverse each element of the array { 
    //  if a character.toInt is in the dictionary, insert into dictionary 
    //  exit loop, with the character which broke the loop 
    //  else 
    //  set dictionary(character.toInt) to true and continue looping 
    // } 
} 

는 예를 들어, 사용 사례입니다 :

val word = "abcdefggghijklmnopqrstuvqxyz".toArray 
val charThatBrokeIt = isUnique(word) 

편집 : 제안 또는 부울, 튜플, 케이스 클래스로,뿐만 아니라 다른 반환 형식을 제안 자유롭게 또는 다른 어떤 것. Option[Char]은 내 결과가 좋지 않을 수 있습니다. 예를 들어. 루프가 일찌감치 (단락)했을 경우에는 false을 돌려 줄지도 모릅니다.

+0

거기에 대한 답변은'var'을 사용합니다. 나는'var'을 피하기 위해 최선을 다하고 있습니다. var를 사용하지 않는 링크로부터의 유일한 응답은 긴 tail tail recursive 패턴 매칭을 사용하는 fresskoma 때문입니다. – Angelito

+0

더 나은 질문 제목에 대한 제안 사항이 있으면 알려주십시오. 그들은 중복되지 않습니다. – Angelito

+0

리턴 타입'Option [Char]'는 최적의 타입이 아닐 수도 있으므로, 그 타입도 자유롭게 편집하십시오. 패턴 적용에 적용되거나 적용되지 않을 수있는 사례 클래스에 반환 된 값을 래핑하는 것과 같은 다른 솔루션에 대해서는 찬반 양론이있을 수 있음을 알고 있습니다. – Angelito

답변

1

첫째, 당신은 단지 String 대신 Array[Char]를 사용해야 있도록 String 이미 콜렉션과 같은 역할을합니다. 둘째로, .view을 사용하여 알고리즘을 부분으로 분할하면서 단락을 허용하기 위해 게으름을 이용할 수 있습니다.

def breaksUnique(word: String): Option[Char] = { 
    val cumulativeSets = word.view.scanLeft(Set.empty[Char]){_ + _} 
    val zipped = cumulativeSets zip word 
    val nonDupsDropped = zipped dropWhile {case (set, char) => !(set contains char)} 
    nonDupsDropped.map{_._2}.headOption 
} 

처음 두 줄

은 전체 단어를 처리하는 경우로서 기록되지만,이 도면에서 동작하기 때문에 필요에 따라, 그들 만 계산된다.

cumulativeSets은 그 시점까지 보이는 모든 문자들의 집합입니다. "abb"에서 실행하면 Set(), Set(a), Set(a,b), Set(a,b)이됩니다. 이는 zip을 사용하여 원래 단어와 결합되어 (Set(),a), (Set(a),b), (Set(a,b),b)이됩니다. 우리는 문자가 집합에 나타나지 않는 모든 쌍을 삭제하고 놓지 않은 첫 번째 요소를 반환해야합니다.

+0

와우. 이것은 매우 간결하고 놀라운 솔루션입니다. 나는 여전히 그 대부분을 무너 뜨리고있다. 그러나 이것은 내가 찾고 있었던 것의 라인을 따른다! 단락 회로 평가, 불변성 및 '보기'를 사용하여 실행 시간을 고려하는 솔루션을 사용하는 솔루션을 찾고있었습니다. 이 솔루션에 대해 가장 좋아하는 것은 세트를 사용하고 예상되는 함수 동작을 더 명확하게 설명 할 수 있다는 것입니다. 'dropWhile','scanLeft' 및 Sets는 확실히 아직 편안하지는 않지만, 훌륭한 사용 사례를 보여 줬습니다! – Angelito

1

초기 브레이크 아웃은 항상 재귀를 제안합니다.

def isUnique(array: Array[Char]): Option[Char] = { 
    def getDup(index: Int, acc: Set[Char]): Option[Char] = 
    if (array.isDefinedAt(index)) 
     if (acc(array(index))) Some(array(index)) 
     else getDup(index+1, acc + array(index)) 
    else None 
    getDup(0, Set.empty[Char]) 
} 

사용법 :

val word = "abcdefggghijklmnopqrstuvqxyz".toArray 
val charThatBrokeIt = isUnique(word) 
//charThatBrokeIt: Option[Char] = Some(g) 
+0

'get'은 과도한 것 같습니다.'getDup'은 항상 -1이나 유효한 인덱스를 반환합니다. –

+1

@JoePallas; 결과를'Option'으로 감싸는 것은 간결한 방법 이었지만, 거기에 갈 수있는 더 좋은 방법이 있습니다. – jwvh

+0

@jwvh 감사합니다. 필자는 Option [Char] 유형이 귀하의 솔루션을 제한하지 않기를 정말로 희망합니다. 결과에 대한 더 나은 제안이 있을까요? 부울을 반환하는 방법에 대해 생각했지만 더 많은 값을 추가하거나 줄일 지 확실하지 않았습니다. 중복 된 편지가 없다면 나는 None을 확인할 수 있었기 때문에. – Angelito