Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have text inputed by my user for example GSM=-73dBm, each time a user enters a piece of text it will always have the same letters and equals sign the only thing that will change is the number and if it is positive or negative. With each range of values the result changes for example -1 to -70 is bad, 0 to 50 is good and 51 to 100 is excellent. The only way i can think of doing this is listed each value the user could enter. Like below.
if ([myTextField.text isEqual:#"GSM=-73dBm"]) {
myTextField.text = #"bad";
} else if {
etc..}
There must be an easier way to do check this.
NSString* target = #"GSM=-73dBm";
NSScanner* sc = [[NSScanner alloc] initWithString:target];
[sc scanUpToString:#"=" intoString:nil];
[sc scanString:#"=" intoString:nil];
NSInteger i;
[sc scanInteger:&i];
Now i is the number -73 and you can just do a couple of tests to see what range it's in.
So you can filter out all non numerical values like this.
NSString *stringToFilter = #"GSM=-73dBm";
NSMutableString *targetString = [NSMutableString string];
//these are characters that you want to keep, so numbers and negative sign
NSCharacterSet *required = [NSCharacterSet characterSetWithCharactersInString:#"-0123456789"];
for(int i = 0; i < [stringToFilter length]; i++)
{
unichar curChar = [stringToFilter characterAtIndex:i];
if([required characterIsMember:curChar])
{
[targetString appendFormat:#"%C", curChar];
}
}
//convert string to int value
int yourNumber = targetString.intValue;
NSLog(#"%d",yourNumber);
This will print "-73".
Then from here you could if else and check if values are contained in a certain range.
You could extract the number with regular expression
NSString *string = #"GSM=-73dBm";
NSString *pattern = #"-?\\d+";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:nil error:&error];
if (!error) {
NSRange result = [regex rangeOfFirstMatchInString:string options: nil range: NSMakeRange(0, string.length)];
NSInteger number = [[string substringWithRange:result] integerValue];
NSLog(#"%ld", number);
} else {
NSLog(#"%#", error);
}
The pattern:
-? An optional minus sign, if there could also be a plus sign, use [+-]?
\\d+ One or more numeric characters
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have a alpha numeric string as 24 minutes i want to trim it like 24mplease tell me how can i do this ?
try use code in regex:
NSString *string = #"24 minutes";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"([0-9]+)[^a-zA-Z]*([a-zA-Z]{1}).*" options:NSRegularExpressionCaseInsensitive error:nil];
NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#"$1$2"];
NSLog(#"%#", modifiedString);
output:
24m
You can use the componentsSeparatedByString: and substringToIndex: methods of NSString Class, to achieve the result.
NSString *str = #"24 minutes";
NSArray *components = [str componentsSeparatedByString:#" "];
// Validation to prevent array out of index crash (If input is 24)
if ([components count] >= 2)
{
NSString *secondStr = components[1];
// Validation to prevent crash (If input is 24 )
if (secondStr.length)
{
NSString *shortName = [secondStr substringToIndex:1];
str = [NSString stringWithFormat:#"%#%#",components[0],shortName];
}
}
NSLog(#"%#",str);
This example works with the above string, however you need to take care of different type of inputs. It can fail if there is multiple spaces between those values.
NSString *aString = #"24 minutes"; // can be "1 minute" also.
First divide the string into two components:
Divide it with white space, since your string can contain one or more number also like "1 minute", "24 mintutes".
NSArray *array = [aString componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF != ''"]];
NSLog(#"%#",[array objectAtIndex:0]);
Then fetch the first letter of the second component of the string using substringToIndex and finally combine both the strings.
NSString * firstLetter = [[array objectAtIndex:1] substringToIndex:1];
NSString *finalString = [[array objectAtIndex:0] stringByAppendingString:firstLetter];
NSLog(#"%#",finalString);
My input is like "Hi {{username}}", ie. a string with keywords to replace. However, the input is quite small (~ 10 keywords and 1000 characters total), and I have a million possible keywords stored in a hashtable data structure, each associated to its replacement.
Therefore, I do not want to iterate over the keyword list and try to replace each one in the input for obvious performance reason. I prefer to iterate only once over the input characters by looking for the regex pattern "\{\{.+?\}\}".
In Java, I make use of the Matcher.appendReplacement and Matcher.appendTail methods to do that. But I cannot find a similar API with NSRegularExpression.
private String replaceKeywords(String input)
{
Matcher m = Pattern.compile("\\{\\{(.+?)\\}\\}").matcher(input);
StringBuffer sb = new StringBuffer();
while (m.find())
{
String replacement = getReplacement(m.group(1));
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
return sb.toString();
}
Am I forced to implement such API myself, or did I miss something?
You can achieve this with NSRegularExpression:
NSString *original = #"Hi {{username}} ... {{foo}}";
NSDictionary *replacementDict = #{#"username": #"Peter", #"foo": #"bar"};
NSString *pattern = #"\\{\\{(.+?)\\}\\}";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:0
error:NULL];
NSMutableString *replaced = [original mutableCopy];
__block NSInteger offset = 0;
[regex enumerateMatchesInString:original
options:0
range:NSMakeRange(0, original.length)
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange range1 = [result rangeAtIndex:1]; // range of the matched subgroup
NSString *key = [original substringWithRange:range1];
NSString *value = replacementDict[key];
if (value != nil) {
NSRange range = [result range]; // range of the matched pattern
// Update location according to previous modifications:
range.location += offset;
[replaced replaceCharactersInRange:range withString:value];
offset += value.length - range.length; // Update offset
}
}];
NSLog(#"%#", replaced);
// Output: Hi Peter ... bar
I don't believe you can do what you want directly.
You could look at using RegexKit Lite, specifically the stringByReplacingOccurrencesOfRegex:usingBlock: method, where the replacement block holds your logic from your while loop above to find and return the appropriate replacement.
How can I get the unique characters in an NSString?
What I'm trying to do is get all the illegal characters in an NSString so that I can prompt the user which ones were inputted and therefore need to be removed. I start off by defining an NSCharacterSet of legal characters, separate them with every occurrence of a legal character, and join what's left (only illegal ones) into a new NSString. I'm now planning to get the unique characters of the new NSString (as an array, hopefully), but I couldn't find a reference anywhere.
NSCharacterSet *legalCharacterSet = [NSCharacterSet
characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789-()&+:;,'.# "];
NSString *illegalCharactersInTitle = [[self.titleTextField.text.noWhitespace
componentsSeparatedByCharactersInSet:legalCharacterSet]
componentsJoinedByString:#""];
That should help you. I couldn't find any ready to use function for that.
NSMutableSet *uniqueCharacters = [NSMutableSet set];
NSMutableString *uniqueString = [NSMutableString string];
[illegalCharactersInTitle enumerateSubstringsInRange:NSMakeRange(0, illegalCharactersInTitle.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if (![uniqueCharacters containsObject:substring]) {
[uniqueCharacters addObject:substring];
[uniqueString appendString:substring];
}
}];
Try with the following adaptation of your code:
// legal set
NSCharacterSet *legalCharacterSet = [NSCharacterSet
characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789-()&+:;,'.# "];
// test strings
NSString *myString = #"LegalStrin()";
//NSString *myString = #"francesco#gmail.com"; illegal string
NSMutableCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:myString];
// inverts the set
NSCharacterSet *illegalCharacterSet = [legalCharacterSet invertedSet];
// intersection of the string set and the illegal set that modifies the mutable stringset itself
[stringSet formIntersectionWithCharacterSet:illegalCharacterSet];
// prints out the illegal characters with the convenience method
NSLog(#"IllegalStringSet: %#", [self stringForCharacterSet:stringSet]);
I adapted the method to print from another stackoverflow question:
- (NSString*)stringForCharacterSet:(NSCharacterSet*)characterSet
{
NSMutableString *toReturn = [#"" mutableCopy];
unichar unicharBuffer[20];
int index = 0;
for (unichar uc = 0; uc < (0xFFFF); uc ++)
{
if ([characterSet characterIsMember:uc])
{
unicharBuffer[index] = uc;
index ++;
if (index == 20)
{
NSString * characters = [NSString stringWithCharacters:unicharBuffer length:index];
[toReturn appendString:characters];
index = 0;
}
}
}
if (index != 0)
{
NSString * characters = [NSString stringWithCharacters:unicharBuffer length:index];
[toReturn appendString:characters];
}
return toReturn;
}
First of all, you have to be careful about what you consider characters. The API of NSString uses the word characters when talking about what Unicode refers to as UTF-16 code units, but dealing with code units in isolation will not give you what users think of as characters. For example, there are combining characters that compose with the previous character to produce a different glyph. Also, there are surrogate pairs, which only make sense when, um, paired.
As a result, you will actually need to collect substrings which contain what the user thinks of as characters.
I was about to write code very similar to Grzegorz Krukowski's answer. He beat me to it, so I won't but I will add that your code to filter out the legal characters is broken because of the reasons I cite above. For example, if the text contains "é" and it's decomposed as "e" plus a combining acute accent, your code will strip the "e", leaving a dangling combining acute accent. I believe your intent is to treat the "é" as illegal.
I am developing an iOS app using Xcode 4.6.2.
My app receives from the server lets say for example 1000 characters which is then stored in NSString.
What I want to do is: split the 1000 characters to multiple strings. Each string must be MAX 100 characters only.
The next question is how to check when the last word finished before the 100 characters so I don't perform the split in the middle of the word?
A regex-based solution:
NSString *string = // ... your 1000-character input
NSString *pattern = #"(?ws).{1,100}\\b";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: pattern options: 0 error: &error];
NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];
NSMutableArray *result = [NSMutableArray array];
for (NSTextCheckingResult *match in matches) {
[result addObject: [string substringWithRange: match.range]];
}
The code for the regex and the matches part is taken directly from the docs, so the only difference is the pattern.
The pattern basically matches anything from 1 to 100 characters up to a word boundary. Being a greedy pattern, it will give the longest string possible while still ending with a whole word. This ensures that it won't split any words in the middle.
The (?ws) makes the word recognition work with Unicode's definition of word breaks (the w flag) and treat a line end as any other character (the s flag).
Notice that the algorithm doesn't handle "words" with more than 100 characters well - it will give you the last 100 characters and drop the first part, but that should be a corner case.
(assuming your words are separated by a single space, otherwise use rangeOfCharacterFromSet:options:range:)
Use NSString -- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)aRange with:
aString as #" "
mask as NSBackwardsSearch
Then you need a loop, where you check that you haven't already got to the end of the string, then create a range (for use as aRange) so that you start 100 characters along the string and search backwards looking for the space. Once you find the space, the returned range will allow you to get the string with substringWithRange:.
(written freehand)
NSRange testRange = NSMakeRange(0, MIN(100, sourceString.length));
BOOL complete = NO;
NSMutableArray *lines = [NSMutableArray array];
while (!complete && (testRange.location + testRange.length) < sourceString.length) {
NSRange hitRange = [sourceString rangeOfString:#"" options:NSBackwardsSearch range:testRange];
if (hitRange.location != NSNotFound) {
[lines addObject:[sourceString substringWithRange:hitRange];
} else {
complete = YES;
}
NSInteger index = hitRange.location + hitRange.length;
testRange = NSMakeRange(index, MIN(100, sourceString.length - index));
}
This can help
- (NSArray *)chunksForString(NSString *)str {
NSMutableArray *chunks = [[NSMutableArray alloc] init];
double sizeChunk = 100.0; // or whatever you want
int length = 0;
int loopSize = ceil([str length]/sizeChunk);
for (int index = 0; index < loopSize; index++) {
NSInteger newRangeEndLimit = ([str length] - length) > sizeChunk ? sizeChunk : ([str length] - length);
[chunks addObject:[str substringWithRange:NSMakeRange(length, newRangeEndLimit)];
length += 99; // Minus 1 from the sizeChunk as indexing starts from 0
}
return chunks;
}
use NSArray *words = [stringFromServer componentsSeparatedBy:#" "];
this will give you words.
if you really need to make it nearest to 100 characters, start appending strings maintaining the total length of the appended strings and check that it should stay < 100.
I'm new to IOS, and was looking for some guidance.
I have a long NSString that I'm parsing out. The beginning may have a few characters of garbage (can be any non-letter character) then 11 digits or spaces, then a single letter (A-Z). I need to get the location of the letter, and get the substring that is 11 characters behind the letter to 1 character behind the letter.
Can anyone give me some guidance on how to do that?
Example: '!!2553072 C'
and I want : '53072 '
You can accomplish this with the regex pattern: (.{11})\b[A-Z]\b
The (.{11}) will grab any 11 characters and the \b[A-Z]\b will look for a single character on a word boundary, meaning it will be surrounded by spaces or at the end of the string. If characters can follow the C in your example then remove the last \b. This can be accomplished in Objective-C like so:
NSError *error;
NSString *example = #"!!2553072 C";
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"(.{11})\\b[A-Z]\\b"
options:NSRegularExpressionCaseInsensitive
error:&error];
if(!regex)
{
//handle error
}
NSTextCheckingResult *match = [regex firstMatchInString:example
options:0
range:NSMakeRange(0, [example length])];
if(match)
{
NSLog(#"match: %#", [example substringWithRange:[match rangeAtIndex:1]]);
}
There may be a more elegant way to do this involving regular expressions or some Objective-C wizardry, but here's a straightforward solution (personally tested).
-(NSString *)getStringContent:(NSString *)input
{
NSString *substr = nil;
NSRange singleLetter = [input rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
if(singleLetter.location != NSNotFound)
{
NSInteger startIndex = singleLetter.location - 11;
NSRange substringRange = NSMakeRange(start, 11);
substr = [tester substringWithRange:substringRange];
}
return substr;
}
You can use NSCharacterSets to split up the string, then take the first remaining component (consisting of your garbage and digits) and get a substring of that. For example (not compiled, not tested):
- (NSString *)parseString:(NSString *)myString {
NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];
NSArray *components = [myString componentsSeparatedByCharactersInSet:letters];
assert(components.count > 0);
NSString *prefix = components[0]; // assuming relatively new Xcode
return [prefix substringFromIndex:(prefix.length - 11)];
}
//to get rid of all non-Digits in a NSString
NSString *customerphone = CustomerPhone.text;
int phonelength = [customerphone length];
NSRange customersearchRange = NSMakeRange(0, phonelength);
for (int i =0; i < phonelength;i++)
{
const unichar c = [customerphone characterAtIndex:i];
NSString* onechar = [NSString stringWithCharacters:&c length:1];
if(!isdigit(c))
{
customerphone = [customerphone stringByReplacingOccurrencesOfString:onechar withString:#"*" options:0 range:customersearchRange];
}
}
NSString *PhoneAllNumbers = [customerphone stringByReplacingOccurrencesOfString:#"*" withString:#"" options:0 range:customersearchRange];