Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highlight particular characters in the string for all the characters of given string

Particular characters are to be highlighted in red color on the label so I wrote below function which works well, but I want to confirm, is there any other efficient way of doing this ? e.g.

-(NSMutableAttributedString*)getAttributeText:(NSString*)string forSubstring:(NSString*)searchstring {
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:_lblName.text];
    NSRange searchRange = NSMakeRange(0,string.length);
    for (NSInteger charIdx=0; charIdx<searchstring.length; charIdx++){
        NSString *substring = [searchstring substringWithRange:NSMakeRange(charIdx, 1)];
        NSRange foundRange;
        searchRange.location = 0;
        while (searchRange.location < string.length) {
            searchRange.length = string.length-searchRange.location;
            foundRange = [string rangeOfString:substring options:1 range:searchRange];
            [text addAttribute: NSForegroundColorAttributeName value: [UIColor redColor] range:foundRange];
            if (foundRange.location != NSNotFound) {
                searchRange.location = foundRange.location+foundRange.length;
            } else {
                // no more substring to find
                break;
            }
        }
    }
    return text;
}

Below is the code how I use it, and result as well

NSString *string = @"James Bond Always Rocks";
_lblName.text = string;
_lblAttributedName.attributedText = [self getAttributeText:string forSubstring:@"ao"];

enter image description here

Update

NSString *string = @"James Bond Always Rocks";    
NSRange range = [string rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"J"] options:NSCaseInsensitiveSearch];
NSLog(@"range->%@",NSStringFromRange(range)); //This prints range->{0, 1}

NSString *string = @"James Bond Always Rocks";    
NSRange range = [string rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"j"] options:NSCaseInsensitiveSearch];
NSLog(@"range->%@",NSStringFromRange(range)); //This prints range->{2147483647, 0}
like image 500
Janak Nirmal Avatar asked Dec 15 '22 00:12

Janak Nirmal


2 Answers

You can simplify it by searching for a pattern ("[ao]+" in your example) to eliminate the outer loop:

NSString *string = @"James Bond Always Rocks";
NSString *searchstring = @"ao";
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:string];

// A regular expression pattern that matches a sequence of the characters in "searchString":
NSString *pattern = [NSString stringWithFormat:@"[%@]+", [NSRegularExpression escapedPatternForString:searchstring]];

NSRange foundRange = [string rangeOfString:pattern options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
while (foundRange.location != NSNotFound) {
    [text addAttribute: NSForegroundColorAttributeName value: [UIColor redColor] range:foundRange];
    NSRange nextRange = NSMakeRange(foundRange.location + foundRange.length, string.length - foundRange.location - foundRange.length);
    foundRange = [string rangeOfString:pattern options:NSRegularExpressionSearch|NSCaseInsensitiveSearch range:nextRange];
}
like image 85
Martin R Avatar answered Mar 15 '23 23:03

Martin R


Here is my version, this is very basic approach using simple loops.

Why I posted it because I tracked the efficiency and please see the time taken by each of the implementations.

2014-03-14 15:48:42.792 TimeEfficiency[1166:303] My: 0.000073 seconds

2014-03-14 15:48:45.319 TimeEfficiency[1166:303] martin: 0.000278 seconds

2014-03-14 15:48:48.263 TimeEfficiency[1166:303] avt: 0.000029 seconds

2014-03-14 15:48:51.152 TimeEfficiency[1166:303] janak: 0.000092 seconds

Hence Avt's is best in time-performance.


NSString *string = @"James Bond Always Rocks";
NSString *searchstring = @"ao";

NSMutableArray *characters = [NSMutableArray new];
for (NSInteger i=0; i<searchstring.length; i++) {
    [characters addObject:[searchstring substringWithRange:NSMakeRange(i, 1)]]; //ao
}
//store all the location of each of the char
NSMutableArray *locations = [NSMutableArray new];
for (NSInteger i=0; i<string.length; i++) {
    if ([characters containsObject: [string substringWithRange:NSMakeRange(i, 1)]] ){
        [locations addObject:@(i)];
    }
}

//loop for string and for each location change the color

NSMutableAttributedString *text = [[NSMutableAttributedString alloc]initWithString:string];
for (NSInteger i=0; i<locations.count; i++) {
    NSRange range=NSMakeRange([locations[i] intValue], 1);
    [text addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
}
like image 35
Anoop Vaidya Avatar answered Mar 16 '23 00:03

Anoop Vaidya