Multiple colors in NSTextField - objective-c

I need to change the color for words that are repeating in each line in NSTextField.
I'm using dictionary to separate each line and the dictionary has and array which separates words as data, then i'm checking if the words are repeated and i want to change color or highlight the words that are repeating.. not sure how to do it.
The program is to get word frequency and show type-token, mean frequency and words that are repeating (text colour/highlighted)
any help would be great. right now i'm assigning text to text field from the .txt file imported. got the repeating words and everything.. just need to show which.
current code:
-(NSMutableDictionary*) computeWords:(NSMutableDictionary *)linesDic{
int count = (int)[linesDic count];
int numberOfwords = 0;
int numberOfDiffWords = 0;
NSMutableDictionary* wordComputation = [[NSMutableDictionary alloc]init];
NSMutableDictionary* duplicates = [[NSMutableDictionary alloc]init];
for (int x = 1; x<=count; x++) {
NSMutableArray* duplicateWords = [[NSMutableArray alloc]init];
NSMutableArray* counter = [[NSMutableArray alloc]init];
NSString* key = [NSString stringWithFormat:#"%d", x];
NSArray* data = [linesDic objectForKey:key];
numberOfwords = (int)[data count];
numberOfDiffWords = numberOfwords;
for (int j = 0; j<numberOfwords; j++) {
for (int k = j+1; k<numberOfwords; k++) {
if([[data objectAtIndex:k]isEqualToString:[data objectAtIndex:j]])
{
numberOfDiffWords--;
[duplicateWords addObject:[data objectAtIndex:k]];
// NSLog(#"%#", [data objectAtIndex:k]);
// NSLog(#"%#", [data objectAtIndex:j]);
}else{
NSString* a = [data objectAtIndex:k];
NSString* b = [data objectAtIndex:j];
if(a.length<b.length){
if((b.length - a.length)<=4){
if([[b substringToIndex:a.length]isEqualToString:a])
{
// NSLog(#"KEY: %# comapare b:%d:%# and a:%d:%#", key,(int)b.length, b, (int)a.length, a );
// NSLog(#"Key: %#, %#", key, [b substringFromIndex:(a.length-1)]);
if([[b substringFromIndex:(a.length)]isEqualToString:#"s"] || [[b substringFromIndex:(a.length)]isEqualToString:#"es"]){
if (([a isEqualToString:#"a"] && [b isEqualToString:#"as"])) {
// NSLog(#"break at key: %#, words %#:%#",key, a, b);
break;
}
numberOfDiffWords--;
[duplicateWords addObject:[data objectAtIndex:k]];
[duplicateWords addObject:[data objectAtIndex:j]];
// NSLog(#"%#", [data objectAtIndex:k]);
// NSLog(#"%#", [data objectAtIndex:j]);
}
}
}
}else{
if((a.length - b.length)<=4){
if([[a substringToIndex:b.length]isEqualToString:b])
{
// NSLog(#"KEY: %# compare a:%d: %# and b:%d: %#", key,(int)a.length, a, (int)b.length, b );
// NSLog(#"Key: %#, %#", key, [a substringFromIndex:(b.length-1)]);
if([[a substringFromIndex:(b.length)]isEqualToString:#"s"] || [[a substringFromIndex:(b.length)]isEqualToString:#"es"]){
if (([a isEqualToString:#"as"] && [b isEqualToString:#"a"])) {
// NSLog(#"break at key: %#, words %#:%#",key, a, b);
break;
}
numberOfDiffWords--;
[duplicateWords addObject:[data objectAtIndex:k]];
[duplicateWords addObject:[data objectAtIndex:j]];
// NSLog(#"%#", [data objectAtIndex:k]);
// NSLog(#"%#", [data objectAtIndex:j]);
}
}
}
}
}
}
}
NSNumber* nw = [NSNumber numberWithInt:numberOfwords];
NSNumber* ndw = [NSNumber numberWithInt:numberOfDiffWords];
[counter addObject:nw];
[counter addObject:ndw];
NSLog(#"Key: %#, Data: %#", key, duplicateWords);
[duplicates setObject:duplicateWords forKey:key];
[wordComputation setObject:counter forKey:key];
}
_duplicates = duplicates;
NSLog(#"%#", _duplicates);
_wordComputation = wordComputation;
return wordComputation;
}
-(void)showTable:(NSMutableDictionary*)wordComputation{
int count = (int)[wordComputation count];
int numberOfwords = 0;
int numberOfDiffWords = 0;
// NSLog(#"\t \t Diff Words Words Type Token \t Mean");
for (int x = 1; x<=count; x++) {
NSString* key = [NSString stringWithFormat:#"%d", x];
NSArray* data = [wordComputation objectForKey:key];
numberOfwords = [[data objectAtIndex:0]intValue];
numberOfDiffWords = [[data objectAtIndex:1]intValue];
//print log
// NSLog(#"Line: %# \t %# \t %# \t %# \t\t %#", key, numberOfDiffWords<10?[NSString stringWithFormat:#"0%d", numberOfDiffWords]:[NSString stringWithFormat:#"%d", numberOfDiffWords], numberOfwords<10?[NSString stringWithFormat:#"0%d", numberOfwords]:[NSString stringWithFormat:#"%d", numberOfwords],[NSString stringWithFormat:#"%d/%d", numberOfDiffWords, numberOfwords], [NSString stringWithFormat:#"%d/%d", numberOfwords, numberOfDiffWords]);
}
[_frequencyTable reloadData];
}
tried this just to change color for string first but then it shows
{
NSColor = "NSCalibratedRGBColorSpace 1 0 0 1";
}
on the 5th position in string
- (IBAction)ViewDuplicatesPressed:(id)sender {
[_duplicatesTextField setHidden:NO];
NSLog(#"%#", _duplicates);
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:#"%#", [_contentTextField stringValue]] /*attributes:#{NSForegroundColorAttributeName : [NSColor redColor]}*/];
[attributedString addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(0,5)];
[_duplicatesTextField setStringValue:[NSString stringWithFormat:#"%#", attributedString]];
}
Also Tried
int lineCount = (int)[_linesDic count];
NSString* key;
NSMutableDictionary* dupliDic = [[NSMutableDictionary alloc]init];
for (int i = 0; i<lineCount; i++) {
NSArray *duplicateWords;
key = [NSString stringWithFormat:#"%d", i];
duplicateWords = [_duplicates objectForKey:key];
NSMutableAttributedString *attributedString;
NSString* stringForKey = [NSString stringWithFormat:#"%#", [_linesDic objectForKey:key]];
for (int j =0 ; i < (int)[duplicateWords count]; j++) {
NSString* word = [duplicateWords objectAtIndex:j];
NSRange range = [stringForKey rangeOfString:word];
attributedString = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:#"%#", [_linesDic objectForKey:key]] /*attributes:#{NSForegroundColorAttributeName : [NSColor redColor]}*/];
[attributedString addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:range];
}
[dupliDic setObject:attributedString forKey:key];
}
[_duplicatesTextField setHidden:NO];
NSLog(#"%#", dupliDic);
[_duplicatesTextField setStringValue:[NSString stringWithFormat:#"%#", dupliDic]];

Related

combine multiple array values into one string value?

I want to combine the array values into one string.
my arrays are like...
array1=[#"fizan",#"nike",#"pogo"];
array2=[#"round",#"rectangle",#"square"];
array3=[#"frame",#"frame",#"frame"];
I need like this...
value1 = fizan round frame
value2 = nike rectangle frame
value3 = pogo square frame
try this:
NSArray *array1= #[#"fizan",#"nike",#"pogo"];
NSArray *array2= #[#"round",#"rectangle",#"square"];
NSArray *array3= #[#"frame",#"frame",#"frame"];
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:#[array1,array2,array3]];
NSMutableArray *output = [[NSMutableArray alloc] init];
NSString *a;
NSInteger count = array.count;
for (int i = 0; i<array1.count; i++) {
a = #"";
for (int j = 0; j<count; j++) {
a = [a isEqualToString: #""] ? [NSString stringWithFormat:#"%#",[[array objectAtIndex:j] objectAtIndex:i]] : [NSString stringWithFormat:#"%# %#",a,[[array objectAtIndex:j] objectAtIndex:i]];
}
[output addObject:a];
}
for (int i = 0; i < output.count; i++) {
NSLog(#"value %i -> %#",i+1,output[i]);
}
Hope this helps!
UPDATE:
NSArray *array1= #[#"fizan",#"",#"pogo"];
NSArray *array2= #[#"round",#"rectangle",#"square"];
NSArray *array3= #[#"frame",#"frame",#"frame"];
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:#[array1,array2,array3]];
NSMutableArray *output = [[NSMutableArray alloc] init];
NSString *a;
NSInteger count = array.count;
for (int i = 0; i<array1.count; i++) {
a = #"";
for (int j = 0; j<count; j++) {
a = [a isEqualToString: #""] ? [NSString stringWithFormat:#"%#",[[array objectAtIndex:j] objectAtIndex:i]] : [NSString stringWithFormat:#"%# %#",a,[[array objectAtIndex:j] objectAtIndex:i]];
}
[output addObject:a];
}
for (int i = 0; i < output.count; i++) {
NSLog(#"value %i -> %#",i+1,output[i]);
}
I have tested this code. It works perfect. Check again and reconsider the issue.
Do this
NSArray *array1 = #[#"fizan", #"nike", #"pogo"];
NSString *value = [array1 componentsJoinedByString:#" "];
NSLog(#"value = %#", value);
Output will get like
value = fizan nike pogo
For your case
NSArray *completeArray = #[#[#"fizan",#"nike",#"pogo"], #[#"round",#"rectangle",#"square"], #[#"frame",#"frame",#"frame"]];
NSMutableArray *resultArray = [NSMutableArray array];
unsigned long count = 1;
for (int i = 0; i< count; i++) {
NSMutableArray *listArray = [NSMutableArray array];
for (NSArray *itemArray in completeArray) {
count = MAX(count,itemArray.count);
if (i < itemArray.count) {
[listArray addObject:itemArray[i]];
}
}
[resultArray addObject:listArray];
}
for (NSArray *itemArray in resultArray) {
NSString *value = [itemArray componentsJoinedByString:#" "];
NSLog(#"value = %#", value);
}
output
value = fizan round frame
value = nike rectangle frame
value = pogo square frame

hackerrank.com find-hackerrank solution on Obj-C

I'm trying to solve https://www.hackerrank.com/challenges/find-hackerrank on Obj-C, and get ok output via xCode, but not via hackerrank's "Run Code" button.
xCode output:
hackerrank output:
So it is at leat strange to see different outputs.
my code:
#import <Foundation/Foundation.h>
int main()
{
NSFileHandle *input;
NSData *inputData;
NSString *match = #"hackerrank";
int amount;
NSString *str;
input = [NSFileHandle fileHandleWithStandardInput];
inputData = [input availableData];
amount = [[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding] intValue];
for (int j = 0; j < amount; j++)
{
inputData = [input availableData];
str = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];
str = [str stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSArray *redexArr = #[match,
[NSString stringWithFormat:#"^%#.+", match],
[NSString stringWithFormat:#".+%#$", match]
];
for (int i = 2; i>=-1; i--)
{
if (i <= -1)
{
printf("-1\n");
} else
{
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", redexArr[i]];
if ([pred evaluateWithObject:str])
{
printf("%d\n", i);
break;
}
}
}
}
return 0;
}
Any ideas?
The difference between the run in Xcode and on HackerRank is that when you run locally, the call to
[input availableData];
stops when your program have read the next line from console. This lets you call availableData multiple times, each time getting the next line.
On HackerRank, though the very first call of availableData gets the entire file, leaving nothing to the rest of your program to consume.
You can fix this problem by reading the file line-by-line, or reading the entire content, and splitting it on end-of-line markers.
Here is your fixed submission that passes all tests on HackerRank:
#import <Foundation/Foundation.h>
int main()
{
NSFileHandle *input;
NSString *match = #"hackerrank";
int amount;
input = [NSFileHandle fileHandleWithStandardInput];
NSArray *inputData = [[[NSString alloc] initWithData:[input availableData] encoding:NSUTF8StringEncoding] componentsSeparatedByString: #"\n"];
amount = [inputData[0] intValue];
for (int j = 1; j <= amount; j++)
{
NSString *str = inputData[j];
NSArray *redexArr = #[match,
[NSString stringWithFormat:#"^%#.+", match],
[NSString stringWithFormat:#".+%#$", match]
];
for (int i = 2; i>=-1; i--)
{
if (i <= -1)
{
printf("-1\n");
} else
{
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", redexArr[i]];
if ([pred evaluateWithObject:str])
{
printf("%d\n", i);
break;
}
}
}
}
return 0;
}

Split NSString with multiple delimiters?

For text bozo__foo!!bar.baz, how to split an NSString containing this into (bozo, foo, bar, baz)?
That is, separe it in components with strings (delimiters) __, !! and ..
You can split the strings using NSCharacterSet. Try this
NSString *test=#"bozo__foo!!bar.baz";
NSString *sep = #"_!.";
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:sep];
NSArray *temp=[test componentsSeparatedByCharactersInSet:set];
NSLog(#"temp=%#",temp);
I'm aware that this question has already been answered but this is a way to separate strings using multiple strings. This is a category to NSString.
- (NSArray<NSString *> *)componentsSeparatedByStrings:(NSArray<NSString *> *)separators
{
NSMutableArray<NSString *> *components = [[NSMutableArray alloc] init];
unichar buffer[self.length + 1];
NSInteger currentOrigin = 0;
NSInteger currentLength = 0;
[self getCharacters:buffer];
for(NSInteger i = 0; i < self.length; i++)
{
unichar currentChar = buffer[i];
currentLength++;
for(NSInteger n = 0; n < separators.count; n++)
{
NSString *currentDivider = [separators objectAtIndex:n];
if(currentDivider.length == 0)
{
return #[self];
}
else if(currentDivider.length > 1)
{
BOOL goodMatch = NO;
for(NSInteger x = 0; x < currentDivider.length; x++)
{
unichar charInDivider = [currentDivider characterAtIndex:x];
if(charInDivider == currentChar)
{
goodMatch = YES;
}
else
{
goodMatch = NO;
break;
}
if(goodMatch == YES && ((x + 1) != currentDivider.length))
{
i++;
currentLength++;
currentChar = buffer[i];
}
}
if(goodMatch == YES)
{
NSRange newComponentRange = NSMakeRange(currentOrigin, (currentLength - currentDivider.length));
NSString *newComponent = [self substringWithRange:newComponentRange];
currentOrigin = (i + 1);
currentLength = 0;
[components addObject:newComponent];
NSLog(#"%#", components);
}
}
else // If current divider is only one character long.
{
if([currentDivider characterAtIndex:0] == currentChar)
{
NSRange newComponentRange = NSMakeRange(currentOrigin, (currentLength - 1));
NSString *newComponent = [self substringWithRange:newComponentRange];
currentOrigin = (i + 1);
currentLength = 0;
[components addObject:newComponent];
break;
}
}
}
// Handle the end of the string.
if((i + 1) == self.length)
{
NSRange newComponentRange = NSMakeRange(currentOrigin, currentLength);
NSString *newComponent = [self substringWithRange:newComponentRange];
currentOrigin = 0;
currentLength = 0;
[components addObject:newComponent];
}
}
return components;
}
Example: "ABCD__EFGHI__JKLMNOP-QRST.UV_WXYZ"
NSLog(#"%#", [test componentsSeparatedByStrings:#[#"__", #"-", #"."]]);
Log Result: "(ABCD, EFGHI, JKLMNOP, QRST, "UV_WXYZ")"
NSString *text = #"bozo__foo!!bar.baz";
NSArray *split1 = [text componentsSeparatedByString:#"__"];
NSArray *split2 = [[split1 lastObject] componentsSeparatedByString:#"!!"];
NSArray *split3 = [[split2 lastObject] componentsSeparatedByString:#"."];
NSLog(#"%#, %#, %#, %#", split1[0], split2[0], split3[0], split3[1]);
More functional solution is to apply -componentsSeparatedByString: recursively, for each component, which was derived during previous separator application:
NSString Category
- (NSMutableArray<NSString *> *)gvr_componentsSeparatedByStrings:(NSArray<NSString *> *)separators {
if (separators.count == 0) {
return [NSMutableArray arrayWithObject:self];
}
NSString *separator = [separators firstObject];
NSArray *reducedSeparators = [separators gvr_arrayByRemovingFirstObject];
NSArray *components = [self componentsSeparatedByString:separator];
NSMutableArray *result = [NSMutableArray new];
for (NSString *component in components) {
NSMutableArray *subResult = [component gvr_componentsSeparatedByStrings:reducedSeparators];
[result addObjectsFromArray:subResult];
}
return result;
}
NSArray Category
- (NSArray *)gvr_arrayByRemovingFirstObject {
NSMutableArray *result = [NSMutableArray new];
for (NSInteger i = 1; i < self.count; i++) {
[result addObject:self[i]];
}
return [result copy];
}
I solved it for my project by looking for the longest separator, replacing the others with this one, then do the separation on the only one left.
Try this:
NSString *test = #"bozo__foo!!bar.baz";
test = [test stringByReplacingOccurrencesOfString:#"!!" withString:#"__"];
test = [test stringByReplacingOccurrencesOfString:#"." withString:#"__"];
NSArray<NSString *> *parts = [test componentsSeparatedByString:#"__"];

Displaying an array in xcode

I am trying to display the an array with different factors of a number ("prime"). But instead of giving me the int numbers I always get 0,1,2,3,4,5,... .
factors.text = #"";
int factorsNumber;
NSMutableArray *array;
array = [NSMutableArray arrayWithCapacity:5];
for (factorsNumber=1; factorsNumber<=prime; factorsNumber++) {
if (prime%factorsNumber == 0) {
[array addObject:[NSString stringWithFormat:#"%d", factorsNumber]];
}
}
for (int i = 0; i < [array count]; i++) {
[array replaceObjectAtIndex:1 withObject:#"4"];
NSString *temp = [NSString stringWithFormat:#"%d, ", i, [[array objectAtIndex:i] intValue]];
factors.text = [factors.text stringByAppendingString:temp];
}
Replace
NSString *temp = [NSString stringWithFormat:#"%d, ", i, [[array objectAtIndex:i] intValue]];
with
NSString *temp = [NSString stringWithFormat:#"%d, ", [[array objectAtIndex:i] intValue]];
The problem was you were only printing the array index, not the value.

Substring to nth character

I need to substring to the 2nd comma in an NSString.
Input:
NSString *input = #"title, price, Camry, $19798, active";
Desired Output:
NSString *output = #"title, price";
Thanks!
UPDATE:
I have the following but the problem is it needs to skip the last comma:
NSString *output = [input rangeOfString:#"," options:NSBackwardsSearch];
Try this:
- (NSString *)substringOfString:(NSString *)base untilNthOccurrence:(NSInteger)n ofString:(NSString *)delim
{
NSScanner *scanner = [NSScanner scannerWithString:base];
NSInteger i;
for (i = 0; i < n; i++)
{
[scanner scanUpToString:delim intoString:NULL];
[scanner scanString:delim intoString:NULL];
}
return [base substringToIndex:scanner.scanLocation - delim.length];
}
this code should do what you need:
NSString *input = #"title, price, Camry, $19798, active";
NSArray *array = [input componentsSeparatedByString:#","];
NSArray *subArray = [array subarrayWithRange:NSMakeRange(0, 2)];
NSString *output = [subArray componentsJoinedByString:#","];
NSLog(output);
You could split -> splice -> join that string like this in objc:
NSString *input = #"title, price, Camry, $19798, active";
// split by ", "
NSArray *elements = [input componentsSeparatedByString: #", "];
// grab the subarray
NSArray *subelements = [elements subarrayWithRange: NSMakeRange(0, 2)];
// concat by ", " again
NSString *output = [subelements componentsJoinedByString:#", "];
You can try something like this:
NSArray *items = [list componentsSeparatedByString:#", "];
NSString result = #"";
result = [result stringByAppendingString:[items objectAtIndex:0]];
result = [result stringByAppendingString:#", "];
result = [result stringByAppendingString:[items objectAtIndex:1]];
You have to check you have at least two items if you want avoid an exception.
There's really nothing wrong with simply writing the code to do what you want. Eg:
int commaCount = 0;
int i;
for (i = 0; i < input.count; i++) {
if ([input characterAtIndex:i] == (unichar) ',') {
commaCount++;
if (commaCount == 2) break;
}
}
NSString output = nil;
if (commaCount == 2) {
output = [input substringToIndex:i];
}
You could create an NSString category to handle finding nth occurrences of any string. This is example is for ARC.
//NSString+MyExtension.h
#interface NSString(MyExtension)
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string;
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string
options:(NSStringCompareOptions)options;
#end
#implementation NSString(MyExtension)
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string
{
return [self substringToNthOccurrence:nth ofString:string options:0];
}
-(NSString*)substringToNthOccurrence:(NSUInteger)nth
ofString:(NSString*)string
options:(NSStringCompareOptions)options
{
NSUInteger location = 0,
strlength = [string length],
mylength = [self length];
NSRange range = NSMakeRange(location, mylength);
while(nth--)
{
location = [self rangeOfString:string
options:options
range:range].location;
if(location == NSNotFound || (location + strlength) > mylength)
{
return [self copy]; //nth occurrence not found
}
if(nth == 0) strlength = 0; //This prevents the last occurence from being included
range = NSMakeRange(location + strlength, mylength - strlength - location);
}
return [self substringToIndex:location];
}
#end
//main.m
#import "NSString+MyExtension.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
NSString *output = [#"title, price, Camry, $19798, active" substringToNthOccurrence:2 ofString:#","];
NSLog(#"%#", output);
}
}
*I'll leave it as an exercise for someone to implement the mutable versions.