Comment vérifier si une chaîne contient une autre chaîne dans Objective-C?

1212

Comment puis-je vérifier si une chaîne ( NSString) contient une autre chaîne plus petite?

J'espérais quelque chose comme:

NSString *string = @"hello bla bla";
NSLog(@"%d",[string containsSubstring:@"hello"]);

Mais le plus proche que j'ai pu trouver était:

if ([string rangeOfString:@"hello"] == 0) {
    NSLog(@"sub string doesnt exist");
} 
else {
    NSLog(@"exists");
}

Quoi qu'il en soit, est-ce la meilleure façon de savoir si une chaîne contient une autre chaîne?

Jonathan.
la source
1
J'aimerais également le voir ajouté, mais en attendant, il est relativement facile de l'ajouter en tant que catégorie sur NSString.
isaac
2
L'utilisation if ([string rangeOfString:@"hello"] == 0) {...}d'une erreur de non-concordance de type pour NSRange et int. pour résoudre ce problème, vous devez modifier la ligne comme suit:if ([string rangeOfString:@"hello"].length == 0) {...}
Neeku
1
iOS 8 ajoute containsString: et voici un moyen minimalement invasif pour ajouter la prise en charge iOS 7 petersteinberger.com/blog/2014/…
Steve Moser
2
Je suis développeur iOS depuis le début et je revisite constamment cet article pour un copier-coller rapide. Je n'arrive pas à mémoriser celui-ci. Article de stackoverflow le plus visité de mon histoire.
VaporwareWolf
utilisez simplement Swift;)
Fattie

Réponses:

2436
NSString *string = @"hello bla bla";
if ([string rangeOfString:@"bla"].location == NSNotFound) {
  NSLog(@"string does not contain bla");
} else {
  NSLog(@"string contains bla!");
}

La clé remarque que rangeOfString:renvoie une NSRangestructure, et la documentation indique qu'elle renvoie la structure {NSNotFound, 0}si la "meule de foin" ne contient pas l '"aiguille".


Et si vous êtes sur iOS 8 ou OS X Yosemite, vous pouvez maintenant faire: (* REMARQUE: cela plantera votre application si ce code est appelé sur un appareil iOS7).

NSString *string = @"hello bla blah";
if ([string containsString:@"bla"]) {
  NSLog(@"string contains bla!");
} else {
  NSLog(@"string does not contain bla");
}

(C'est aussi ainsi que cela fonctionnerait dans Swift)

👍

Dave DeLong
la source
286
Pour effectuer une recherche insensible à la casse, utilisez "if ([string rangeOfString: @" bla "options: NSCaseInsensitiveSearch] .location! = NSNotFound)"
Vanja
1
@Dave DeLong J'allais juste mentionner une catégorie que j'ai créée à cet effet avant de lire votre modification de la réponse! Comme je suis principalement développeur ac #, je suis heureux qu'ils aient ajouté une méthode contains à NSSTring.
dherrin79
Pourquoi le compilateur ne dit rien si ma cible de déploiement est iOS7 et que j'utilise containsString?
Ricardo
3
Et pour approfondir le point soulevé par @Vanja: si vous allez utiliser le code de raccourci [string containsString] introduit dans iOS 8 / Yosemite, vous pouvez utiliser le code suivant pour une chaîne insensible à la casse: "[stringToSearch localizedCaseInsensitiveContainsString: string ] ", et celui-ci si vous voulez faire une recherche insensible à la casse et aux signes diacritiques:" [stringToSearch localizedStandardContainsString: string] ".
Scott Kohlert
1
Notez que l'expression [string rangeOfString:@"bla"].location != NSNotFoundsera vraie lorsque la chaîne l'est nil!
funroll
158

Pour iOS 8.0+ et macOS 10.10+, vous pouvez utiliser le natif de NSString containsString: .

Pour les anciennes versions d'iOS et de macOS, vous pouvez créer votre propre catégorie (obsolète) pour NSString:

@interface NSString ( SubstringSearch )
    - (BOOL)containsString:(NSString *)substring;
@end

// - - - - 

@implementation NSString ( SubstringSearch )

- (BOOL)containsString:(NSString *)substring
{    
    NSRange range = [self rangeOfString : substring];
    BOOL found = ( range.location != NSNotFound );
    return found;
}

@end

Remarque: Observez le commentaire de Daniel Galasko ci-dessous concernant la dénomination

P i
la source
13
+1 pour un code résultant plus clair et une réutilisabilité. Je l'ai transformé en un liner return [self rangeOfString:substring].location != NSNotFound;et l'ai inclus dans ma bibliothèque de refactoring, es_ios_utils. github.com/peterdeweese/es_ios_utils
Peter DeWeese
4
On dirait qu'Apple aime votre idée et a ajouté cette fonctionnalité dans iOS 8 et OSx 10.10 (Yosemite) comme @DaveDeLong l'a mentionné dans sa réponse. +1
Islam Q.
7
La règle cardinale pour les catégories obj-c est de préfixer le nom de la méthode avec votre préfixe de module à 3 lettres. Ceci est l'exemple parfait car il est maintenant en conflit avec la version iOS 7 et 10.10
Daniel Galasko
54

Étant donné que cela semble être un résultat de haut niveau dans Google, je veux ajouter ceci:

iOS 8 et OS X 10.10 ajoutent la containsString:méthode à NSString. Une version mise à jour de l'exemple de Dave DeLong pour ces systèmes:

NSString *string = @"hello bla bla";
if ([string containsString:@"bla"]) {
    NSLog(@"string contains bla!");
} else {
    NSLog(@"string does not contain bla");
}
Lukas
la source
39
NSString *myString = @"hello bla bla";
NSRange rangeValue = [myString rangeOfString:@"hello" options:NSCaseInsensitiveSearch];

if (rangeValue.length > 0)
{
    NSLog(@"string contains hello");
} 
else 
{
    NSLog(@"string does not contain hello!");
}

// Vous pouvez également utiliser ce qui suit:

if (rangeValue.location == NSNotFound) 
{
    NSLog(@"string does not contain hello");
} 
else 
{
    NSLog(@"string contains hello!");
}
AJS
la source
22

Avec iOS 8 et Swift , nous pouvons utiliser la localizedCaseInsensitiveContainsString méthode

 let string: NSString = "Café"
 let substring: NSString = "É"

 string.localizedCaseInsensitiveContainsString(substring) // true
Govind
la source
1
C'est bon. Aucune idée pourquoi ils n'avaient pas cette méthode pour iOS 7
Lucas
@Lucas, car Swift a été lancé avec iOS 8.0. mais avec swift, vous pouvez toujours prendre en charge les appareils avec iOS 7.
Hemang
13

Donc personnellement je déteste vraiment NSNotFound mais comprends sa nécessité.

Mais certaines personnes peuvent ne pas comprendre la complexité de la comparaison avec NSNotFound

Par exemple, ce code:

- (BOOL)doesString:(NSString*)string containString:(NSString*)otherString {
    if([string rangeOfString:otherString].location != NSNotFound)
        return YES;
    else
        return NO;
}

a ses problèmes:

1) Évidemment, si otherString = nilce code se bloque. un test simple serait:

NSLog(@"does string contain string - %@", [self doesString:@"hey" containString:nil] ? @"YES": @"NO");

résulte en !! CRASH !!

2) Ce qui n'est pas si évident pour quelqu'un de nouveau à objective-c, c'est que le même code ne plantera PAS quand string = nil. Par exemple, ce code:

NSLog(@"does string contain string - %@", [self doesString:nil containString:@"hey"] ? @"YES": @"NO");

et ce code:

NSLog(@"does string contain string - %@", [self doesString:nil containString:nil] ? @"YES": @"NO");

entraînera à la fois

does string contains string - YES

Ce qui n'est clairement pas ce que vous voulez.

Donc, la meilleure solution qui, selon moi, fonctionne est d'utiliser le fait que rangeOfString renvoie la longueur de 0, alors un code plus fiable est le suivant:

- (BOOL)doesString:(NSString*)string containString:(NSString*)otherString {
    if(otherString && [string rangeOfString:otherString].length)
        return YES;
    else
        return NO;
}

OU SIMPLEMENT:

- (BOOL)doesString:(NSString*)string containString:(NSString*)otherString {
    return (otherString && [string rangeOfString:otherString].length);
}

qui reviendra pour les cas 1 et 2

does string contains string - NO

C'est mes 2 cents ;-)

Veuillez consulter mon Gist pour un code plus utile.

ucangetit
la source
12

Une version améliorée de la solution de P i , une catégorie sur NSString, qui non seulement indiquera si une chaîne est trouvée dans une autre chaîne, mais prend également une plage par référence, est:

@interface NSString (Contains)
-(BOOL)containsString: (NSString*)substring
              atRange:(NSRange*)range;

-(BOOL)containsString:(NSString *)substring;
@end

@implementation NSString (Contains)

-(BOOL)containsString:(NSString *)substring
              atRange:(NSRange *)range{

    NSRange r = [self rangeOfString : substring];
    BOOL found = ( r.location != NSNotFound );
    if (range != NULL) *range = r;
    return found;
}

-(BOOL)containsString:(NSString *)substring
{
    return [self containsString:substring
                        atRange:NULL];
}

@end

Utilisez-le comme:

NSString *string = @"Hello, World!";

//If you only want to ensure a string contains a certain substring
if ([string containsString:@"ello" atRange:NULL]) {
    NSLog(@"YES");
}

// Or simply
if ([string containsString:@"ello"]) {
    NSLog(@"YES");
}

//If you also want to know substring's range
NSRange range;
if ([string containsString:@"ello" atRange:&range]) {
    NSLog(@"%@", NSStringFromRange(range));
}
vikingosegundo
la source
8

Voici un extrait de fonction copier-coller:

-(BOOL)Contains:(NSString *)StrSearchTerm on:(NSString *)StrText
{
    return [StrText rangeOfString:StrSearchTerm 
        options:NSCaseInsensitiveSearch].location != NSNotFound;
}
Durai Amuthan.H
la source
Puis-je savoir pourquoi je suis rétrogradé? C'est un extrait de code de travail
Durai Amuthan.H
6

Oneliner (Plus petite quantité de code. SEC, car vous n'en avez qu'un NSLog):

NSString *string = @"hello bla bla";
NSLog(@"String %@", ([string rangeOfString:@"bla"].location == NSNotFound) ? @"not found" : @"cotains bla"); 
Jerik
la source
6
NSString *categoryString = @"Holiday Event";
if([categoryString rangeOfString:@"Holiday"].location == NSNotFound)
{
    //categoryString does not contains Holiday
}
else
{
    //categoryString contains Holiday
}
Ada
la source
5

essaye ça,

NSString *string = @"test Data";
if ([[string lowercaseString] rangeOfString:@"data"].location == NSNotFound) 
{
    NSLog(@"string does not contain Data");
}   
else 
{
    NSLog(@"string contains data!");
}
Pooja Patel
la source
5

Meilleure solution. Aussi simple que ça! Si vous souhaitez rechercher un mot ou une partie de la chaîne. Vous pouvez utiliser ce code. Dans cet exemple, nous allons vérifier si la valeur de word contient "acter".

NSString *word =@"find a word or character here";
if ([word containsString:@"acter"]){
    NSLog(@"It contains acter");
} else {
     NSLog (@"It does not contain acter");
}
handiansom
la source
5

Dans Swift 4:

let a = "Hello, how are you?"
a.contains("Hello")   //will return true
Garg Ankit
la source
4

Si vous en avez besoin une fois, écrivez:

NSString *stringToSearchThrough = @"-rangeOfString method finds and returns the range of the first occurrence of a given string within the receiver.";
BOOL contains = [stringToSearchThrough rangeOfString:@"occurence of a given string"].location != NSNotFound;
Nikolay Shubenkov
la source
4

En cas de swift, cela peut être utilisé

let string = "Package #23"
if string.containsString("Package #") {
    //String contains substring
}
else {
    //String does not contain substring
}
Sreedeepkesav MS
la source
2

Si ne vous souciez pas de la chaîne sensible à la casse. Essayez ceci une fois.

NSString *string  = @"Hello World!";

if([string rangeOfString:@"hello" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    NSLog(@"found");
}
else
{
    NSLog(@"not found");
}
Abhijit
la source
1

Veuillez utiliser ce code

NSString *string = @"hello bla bla";
if ([string rangeOfString:@"bla"].location == NSNotFound) 
{
    NSLog(@"string does not contain bla");
} 
else 
{  
    NSLog(@"string contains bla!");
}
Rohit suvagiya
la source
1

Utilisez l'option NSCaseInsensitiveSearch avec rangeOfString: options:

NSString *me = @"toBe" ;
NSString *target = @"abcdetobe" ;
NSRange range = [target  rangeOfString: me options: NSCaseInsensitiveSearch];
NSLog(@"found: %@", (range.location != NSNotFound) ? @"Yes" : @"No");
if (range.location != NSNotFound) {
// your code
}

Le résultat de sortie est trouvé: Oui

Les options peuvent être "ou" sélectionnées ensemble et comprennent:

NSCaseInsensitiveSearch NSLiteralSearch NSBackwardsSearch et plus

Nayab Muhammad
la source
0

La première chaîne contient ou non la deuxième chaîne,

NSString *first = @"Banana";
NSString *second = @"BananaMilk";
NSRange range = [first rangeOfString:second options:NSCaseInsensitiveSearch];

if (range.length > 0) {
    NSLog(@"Detected");
}
else {
    NSLog(@"Not detected");
}
Kamani Jasmin
la source
0

Essaye ça:

Swift 4.1, 4.2:

let stringData = "Black board"

//swift quick way and case sensitive
if stringData.contains("bla") {
    print("data contains string");
}

//case sensitive
if stringData.range(of: "bla",options: .caseInsensitive) != nil {
    print("data contains string");
}else {
    print("data does not contains string");
}

Pour Objective-C:

NSString *stringData = @"Black board";

//Quick way and case sensitive
if ([stringData containsString:@"bla"]) {
    NSLog(@"data contains string");
}

//Case Insensitive
if ([stringData rangeOfString:@"bla" options:NSCaseInsensitiveSearch].location != NSNotFound) {
   NSLog(@"data contains string");
}else {
   NSLog(@"data does not contain string");
}
Amir.n3t
la source
0

Swift 4 et au-dessus

let str = "Hello iam midhun"

if str.contains("iam") {
  //contains substring
}
else {
  //doesn't contain substring
}

Objectif c

NSString *stringData = @"Hello iam midhun";

if ([stringData containsString:@"iam"]) {
    //contains substring
}
else {
    //doesn't contain substring
}
midhun p
la source
-1
-(Bool)checkIf:(String)parentString containsSubstring:(String)checkString {
    NSRange textRange =[parentString rangeOfString:checkString];
    return textRange.location != NSNotFound // returns true if parent string contains substring else returns false
  }
iOS Népal
la source
1
Dans Objective-C, nous avons le type «NSString». Nous n'avons pas de Stringtype. Deuxièmement, nous avons tous les objets. Donc, comme argument, vous devez passer NSString. Je vote pour la suppression en raison de la mauvaise qualité d'une réponse à une question très active.
Aleksey Potapov
-2

Si une certaine position de la chaîne est nécessaire, ce code vient se placer dans Swift 3.0 :

let string = "This is my string"
let substring = "my"

let position = string.range(of: substring)?.lowerBound
pedrouan
la source