2016-12-19 1 views
-2

Existe-t-il un moyen de rechercher dans un UITableView et d'ignorer certains caractères comme des virgules ou des points?Rechercher un UITableView et ignorer la ponctuation

I.e. Je voudrais rechercher "St George" mais mon ensemble de données contient "St. George" donc le résultat est toujours zéro.

ÉDITÉ Q:

func filteredArray(searchText: NSString) { 
    if searchText == "" { 
     array_search = array_all 
    } else { 
     showTableViewResults() 
     array_search.removeAll() 
     for i in 0 ..< array_all.count { 
      let object:MyObject = array_all[i] 
      let languageSearchString = object.myObjectName 
      let searchStr:String = languageSearchString! 
      if searchStr.lowercased().contains(searchText.lowercased) { 
       array_search.append(object) 
      } 
     } 
    } 
    tableView.reloadData() 
    recordsFoundLabel.text = "records found: \(array_search.count)" 
} 

Répondre

0

Je pense que vous devriez simplement mettre en œuvre une fonction pour une chaîne donnée, retourne te même chaîne sans point, (ou tout ce que vous voulez effacer); tels que:

func erase(characters: [String], fromText text: String) -> String { 
    var result = String() 
    for character in text.characters { 
     if !characters.contains(character) { 
      result += String(character) 
     } 
    } 
    return result 
} 

(? Je ne peux pas le tester à partir de là où je suis, mais vous avez l'idée à droite)

Hope it helps

+0

Il devrait également faire une recherche insensible à la casse (le plus probable). – rmaddy

1

Vous pouvez filtrer tous les caractères thats pas une lettre de votre Chaîne avant d'effectuer votre recherche. La même chose s'applique aux éléments de source de données de vue de table. En outre, comme mentionné par rmaddy vous devez mettre en œuvre une affaire recherche insensible:

extension UnicodeScalar { 
    init?(_ character: Character) { 
     self.init(character.string) 
    } 
} 
extension Character { 
    var unicodeScalar: UnicodeScalar? { 
     return UnicodeScalar(self) 
    } 
    var string: String { 
     return String(self) 
    } 
} 
extension String { 
    func containsCaseInsensitive(_ string: String) -> Bool { 
     return range(of: string, options: .caseInsensitive) != nil 
    } 
    var letters: String { 
     return String(characters.filter{ 
      guard let unicodeScalar = $0.unicodeScalar else { return false } 
      return CharacterSet.letters.contains(unicodeScalar) 
     }) 
    } 
} 

Test:

let search = "st george" 
let tableViewSource = ["Apple", "Orange", "Banana", "St. George"] 

let filtered = tableViewSource.filter { 
    $0.letters.containsCaseInsensitive(search.letters) 
} 
print(filtered) // ["St. George"] 


Si vous souhaitez littéralement juste enlever la ponctuation de votre chaîne (notez que garderait les espaces dans votre chaîne), vous pouvez faire comme suit:

extension String { 
    var removingPunctuation: String { 
     return String(characters.filter { 
      guard let unicodeScalar = $0.unicodeScalar else { return true } 
      return !CharacterSet.punctuationCharacters.contains(unicodeScalar) 
     }) 
    } 
} 

Test:

let filtered = tableViewSource.filter { 
    $0.removingPunctuation.caseInsensitiveContains(search.removingPunctuation) 
} 
print(filtered) // ["St. George"] 

Si vous souhaitez mettre en œuvre la même logique que Xcode autocomplete vous devez faire une recherche pour chaque personnage et changer le startIndex de la chaîne recherché:

extension String { 
    func containsCaseInsensitiveCharactersInSequence(_ string: String) -> Bool { 
     var found = 0 
     var start = startIndex 
     string.characters.forEach { 
      while let range = range(of: String($0), options: .caseInsensitive, range: start..<endIndex) { 
       found += 1 
       start = range.upperBound 
       break 
      } 
     } 
     return found == string.characters.count 
    } 
} 

Test de terrain de jeu:

let search = "stgrge" 
let tableViewSource = ["Apple", "Orange", "Banana", "St. George"] 

let filtered = tableViewSource.filter { 

    $0.removingPunctuation.containsCaseInsensitiveCharactersInSequence(search.removingPunctuation) 

} 
print(filtered) // ["St. George"] 
+0

Ceci est une solution très étrange et hostile à l'utilisateur. Il trouverait "St. George" si l'utilisateur a tapé "Greg" mais pas si l'utilisateur a tapé "george". – rmaddy

+0

Pas tout à fait. La saisie semi-automatique Xcode attend au moins que les caractères du texte de recherche soient trouvés dans le même ordre qu'une valeur correspondante. Si je veux que Xcode me donne la méthode 'contains' sur un objet' String', je peux taper 'otns', par exemple, mais pas' ncs', par exemple. – rmaddy

+0

@LeoDabus merci pour votre réponse. J'utilise un tableau d'objets plutôt qu'un tableau de chaînes de caractères. J'ai donc eu quelques problèmes pour implémenter vos solutions. Voir Q édité pour info. Merci –