在这个传统的Swift代码中,“SubSlice”的新等价物是什么?

时间:2016-03-23 00:16:10

标签: swift

我正在查看this legacy Swift code实施Peter Norvig的拼写检查程序,并遇到了这段代码:

extension Array {
    subscript(r: RangeStart<Int>) -> SubSlice { return self[r.start..<self.endIndex] }
    subscript(r: RangeEnd<Int>) -> SubSlice { return self[self.startIndex..<r.end] }
}

我如何重写,以便SubSlice更新为现在应该是什么?

2 个答案:

答案 0 :(得分:1)

您正在寻找ArraySlice<Element>

struct RangeStart<I: ForwardIndexType> { let start: I }
struct RangeEnd<I: ForwardIndexType> { let end: I }

extension Array {
    subscript(r: RangeStart<Int>) -> ArraySlice<Element> { return self[r.start..<self.endIndex] }
    subscript(r: RangeEnd<Int>) -> ArraySlice<Element> { return self[self.startIndex..<r.end] }
}

/* example usage */
let foo = Array(0...10)
foo[RangeStart<Int>(start: 5)] // [5, 6, 7, 8, 9, 10]
foo[RangeEnd<Int>(end: 6)]     // [0, 1, 2, 3, 4, 5]

let bar = ["1", "2", "3", "4", "5"]
bar[RangeStart<Int>(start: 2)] // ["3", "4", "5"]
bar[RangeEnd<Int>(end: 3)]     // ["1", "2", "3"]

答案 1 :(得分:0)

    // Translation of [Peter Norvig's spell checker](http://norvig.com/spell-correct.html) into Swift.
    // Sample input corpus [here](http://norvig.com/big.txt)

    import Foundation

    extension SequenceType {
      func mapSome<T>(@noescape transform: (Self.Generator.Element) -> T?) -> [T] {
          return Array(self.map(transform).filter { $0 != nil }.map { $0! })
      }
    }

    struct SpellingCorrector {

        var knownWords: [String:Int] = [:]

        init?(contentsOfFile file: String) {
            do {
                let text = try String(contentsOfFile: file, encoding: NSUTF8StringEncoding)
                print("Loaded file \(file)")
                let words = text.lowercaseString.characters.split { !("a"..."z").contains($0) }.map(String.init)
                print("Split string into \(words.count) words")
                for word in words { self.train(word) }
                print("Trained \(knownWords.count) unique words")
            } catch _ as NSError {
                return nil
            }
        }

        mutating func train(word: String) {
            knownWords[word] = knownWords[word]?.successor() ?? 1
        }

        // Given a word, produce a set of possible alternatives with
        // letters transposed, deleted, replaced or rogue characters inserted
        func edits1(word: String) -> Set<String> {
          if word.isEmpty { return [] }

          let splits = word.characters.indices.map {
              return (word[word.startIndex..<$0], word[$0..<word.endIndex])
          }

          let deletes = splits.map {  (left, right) -> String in
              return left + right.substringFromIndex(right.startIndex.advancedBy(1))
          }

          let transposes = (splits + [(word, "")]).mapSome { (left, right) -> String? in
              if let fst = right.characters.first {
                  let drop1 = right.substringFromIndex(right.startIndex.advancedBy(1))
                  if let snd = String(drop1).characters.first {
                      let drop2 = drop1.substringFromIndex(drop1.startIndex.advancedBy(1))
                      return left + String(snd) + String(fst) + drop2
                  }
              }
              return nil
          }

          let alphabet = "abcdefghijklmnopqrstuvwxyz"

          let replaces = splits.flatMap { left, right in
              alphabet.characters.map {
                  left + String($0) + right.substringFromIndex(right.startIndex.advancedBy(1))
              }
          }

          let inserts = (splits + [(word, "")]).flatMap { left, right -> [String] in
              alphabet.characters.map {
                  return left + String($0) + right
              }
          }

          return Set(deletes + transposes + replaces + inserts)
        }

        func knownEdits2(word: String) -> Set<String>? {
            var known_edits: Set<String> = []
            for edit in edits1(word) {
                if let k = known(edits1(edit)) {
                    known_edits.unionInPlace(k)
                }
            }
            return known_edits.isEmpty ? nil : known_edits
        }

        func known<S: SequenceType where S.Generator.Element == String>(words: S) -> Set<String>? {
            let s = Set(words.filter { self.knownWords.indexForKey($0) != nil })
            return s.isEmpty ? nil : s
        }

        func correct(word: String) -> String {
            let candidates = known([word]) ?? known(edits1(word)) ?? knownEdits2(word)

            return (candidates ?? []).reduce(word, combine: {
                (knownWords[$0] ?? 1) < (knownWords[$1] ?? 1) ? $1 : $0
            })
        }
    }

    let tests1 = ["access": "acess", "accessing": "accesing", "accommodation":
    // .../...
        "whether": "wether", "wrote": "rote wote"]

    let tests2 = ["forbidden": "forbiden", "decisions": "deciscions descisions",
    // .../...
        "together": "togehter", "profits": "proffits"]


    func spelltest(tests: [String:String], bias: Int? = nil, verbose: Bool = false) -> [String:Any]{
        var n = 0, bad = 0, unknown = 0, start = NSDate()

        var checker = SpellingCorrector(contentsOfFile: "big.txt")!

        if let bias = bias {
            for target in tests.keys {
                checker.knownWords[target]! += bias
            }
        }

        for (target, wrongs) in tests {
            let strings = wrongs.characters.split{$0 == " "}.map(String.init)
            for wrong in strings {
                n += 1
                let w = checker.correct(wrong)
                if w != target {
                    bad += 1
                    unknown += (checker.knownWords[target] != nil ? 1 : 0)
                    if verbose {
                        print ("\(wrong) => \(w) (\(checker.knownWords[w])); expected \(target) (\(checker.knownWords[target]))")
                    }
                }
            }
        }

        let pct = Int(100.0 - 100.0*Double(bad)/Double(n))
        let end = NSDate()
        return ["bad": bad, "n": n, "bias": bias, "pct": pct, "unknown": unknown, "secs": end.timeIntervalSinceDate(start)]
    }

    print(spelltest(tests1, bias: nil, verbose: true))
    print(spelltest(tests2))