Filtering Innapropriate Content - ios

I have a chatroom that filters inappropriate content near perfectly using an array called blackList (an array of inappropriate words) and iterates through that and replaces inappropriate words with ****'s. However, when it comes across a word like "classy", it stars-out the third through fifth letter. How do I stop this and related problems? Thanks, and here is my code:
- (void)displayChatMessage:(NSString*)message fromUser:(NSString*)userName {
for(int i =0 ;i< blackList.count;i++)
{
NSMutableString* stars = [[NSMutableString alloc]init];
for(int j = 0 ; j <[[blackList objectAtIndex:i] length];j++)
[stars appendString:#"*"];
message = [message stringByReplacingOccurrencesOfString:(NSString*)[blackList objectAtIndex:i] withString:#"***"];
}
[chat appendTextAfterLinebreak:[NSString stringWithFormat:#"%#: %#", userName, message]];
[chat scrollToBottom:chat];
}

Related

What would be a way to get all combinations of a NSString in Objective-C in a specific pattern?

I have a NSString *strName = #"JonnySmith";
What I want to do is get an NSArray of NSStrings with all possible combinations of a name, omitting certain characters. For example:
#"J";
#"Jo";
#"Jon";
but also combinations like:
#"JSmith";
#"JonSmith"
#"JonnSm";
#"JonSmt";
#"Smith";
#"th";
But they need to be in the order of the original name (the characters can't be out of order, just omitted). Basically traversing left to right in a loop, over and over again, until all possible combos are made.
What is the most efficient way to do this in Objective-C without make a mess?
Let's see if we can give you some pointers, everything here is abstract/pseudocode.
There are 2^n paths to follow, where n is the number of characters, as at each character you either add it or do not.
Taking your example after the first character you might produce #"" and #"J", then to each of these you either add the second character or not, giving: #"", #"J" (add nothing), #"o", "#Jo". Observe that if you have repeated characters anywhere in your input, in your sample you have two n's, this process may produce duplicates. You can deal with duplicates by using a set to collect your results.
How long is a character? Characters may consist of sequences of unicode code points (e.g. 🇧🇪 - Belgium flag, if it prints in SO! Letters can be similarly composed), and you must not split these composed sequences while producing your strings. NSString helps you here as you can enumerate the composed sequences invoking a block for each one in order.
The above give you the pseudocode:
results <- empty set
for each composed character in input do block:
add to results a copy of each of its members with the composed character appended
You cannot modify a collection at the same time you enumerate it. So "add to results" can be done by enumerating the set creating a new collection of strings to add, then adding them all at once after the enumeration:
new items <- empty collection
for every item in results
add to new items (item appending composed character)
results union new items
Optimising it slightly maybe: in (2) we had the empty string and in (4) we append to the empty string. Maybe you could not add the empty string to start and initialise new items to the composed character?
Hint: why did I write the non-specific collection in (4)?
Have fun. If you code something up and get stuck ask a new question, describe your algorithm, show what you've written, explain the issue etc. That will (a) avoid down/close votes and (b) help people to help you.
One possibility is to consider every combination to be a mask of bits, where 1 means the character is there and 0 means the character is missing, for example:
100010000 for JonnySmith will mean JS
000000001 for JonnySmith will mean h
It's simple to generate such masks because we can just iterate from 1 (or 000000001) to 111111111.
Then we only have to map that mask into characters.
Of course, some duplicates are generated because 1110... and 1101... will both be mapped to Jon....
Sample implementation:
NSString *string = #"JonnySmith";
// split the string into characters (every character represented by a string)
NSMutableArray<NSString *> *characters = [NSMutableArray array];
[string enumerateSubstringsInRange:NSMakeRange(0, string.length)
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
[characters addObject:substring];
}];
// let's iterate over all masks
// start with zero if you want empty string to be included
NSUInteger min = 1;
NSUInteger max = (1 << characters.count) - 1;
NSMutableString *buffer = [[NSMutableString alloc] initWithCapacity:characters.count];
NSMutableSet *set = [NSMutableSet set];
for (NSUInteger mask = min; mask <= max; mask++) {
[buffer setString:#""];
// iterate over all bits in the generated mask, map it to string
for (NSInteger charIndex = 0; charIndex < characters.count; charIndex++) {
if ((mask & (1 << (characters.count - charIndex - 1))) != 0) {
[buffer appendString:[characters objectAtIndex:charIndex]];
}
}
// add the resulting string to Set, will handle duplicates
[set addObject:[buffer copy]];
}
NSLog(#"Count: %#", #(set.count)); // 767
The size for NSUInteger will give us the maximum number of characters we can use using this method.
Noticed the question is old but no answer is accepted. I think you can generate all permutations and then omit results which don't match your criteria (or tweak this code per your needs)
#interface NSString (Permute)
- (NSSet *)permutations;
#end
#implementation NSString (Permute)
- (NSSet *)permutations {
if ([self length] <= 1) {
return [NSSet setWithObject:self];
}
NSMutableSet *s = [NSMutableSet new];
[s addObject:[self substringToIndex:1]];
for (int i = 1; i < self.length; i++) {
char c = [self characterAtIndex:i];
s = [self words:s insertingLetterAtAllPositions:[NSString stringWithFormat:#"%C",c]];
}
return [s copy];
}
- (NSMutableSet *)words:(NSSet *)words insertingLetterAtAllPositions:(NSString *)letter {
NSMutableSet *collector = [NSMutableSet new];
for (NSString *word in words) {
[collector unionSet:[word allInsertionsOfLetterAtAllPositions:letter]];
}
return collector;
}
- (NSMutableSet *)allInsertionsOfLetterAtAllPositions:(NSString *)letter {
NSMutableSet *collector = [NSMutableSet new];
for (int i = 0; i < [self length] + 1; i++) {
NSMutableString *mut = [self mutableCopy];
[mut insertString:letter atIndex:i];
[collector addObject:[mut copy]];
}
return collector;
}
#end
// usage
[#"abc" permutations];
You can do it quite easily with a little recursion. It works like this:
Check if the length is 1, then return an array of 2 elements, the empty string and the string.
Call recursively with input string minus the first character and assign to sub-result.
Duplicate the sub-result, adding the first character to each string.
Return the result.
Remember to not call for empty string. If you want to omit the empty result string just remove the first element. Also, if you use the same letter several times, you will get some result strings several times. Those can be removed afterwards.
- (void)combinations:(NSString *)string result:(NSMutableArray *)result {
if (string.length == 1) {
[result addObjectsFromArray:#[ #"", string ]];
} else {
[self combinations:[string substringFromIndex:1] result:result];
for (NSInteger i = result.count - 1; i >= 0; --i)
[result addObject:[[string substringToIndex:1] stringByAppendingString:result[i]]];
}
}
// Call like this, for speed only one mutable array is allocated
NSString *test = #"0123456789";
NSMutableArray *result = [NSMutableArray arrayWithCapacity:1 << test.length];
[self combinations:test result:result];

iOS - Displaying Two Words At A Time From String Array

I'm doing an RSVP reading project app where it blinks words on the screen. You can set the word chunk size (how many words you want displayed at a time) to either 1, 2, or 3. I got it working for 1 word by having my paragraph in a string and doing:
[self.textInput componentsSeparatedByString:#" ";
This makes me an array of words that I can use to blink one word at a time. How would I be able to do this with displaying 2 words at a time? Is there a way I can use this function again to do it differently, or should I iterate over this word array and make a new one with 2 word strings?
Any help or advice would be greatly appreciated as to what the best practice would to get this done. Thanks.
just like keith said create an array
NSArray *allwordsArray = [self.textInput componentsSeparatedByString:#" "];
Now you got all the info you need. Meaning you got the array with every word in it. Now its just a matter of putting it together. (I haven't tested this code)
NSMutableArray *twoWordArray = [[NSMutableArray alloc] init];
int counter=0;
for (int i=0; i<[allwordsArray count]; i++)
{
if (counter >= [allwordsArray count]) break;
NSString *str1 = [NSString stringwithformat#"%#", [allwordsArray objectAtIndex:counter]];
counter++;
if (counter >= [allwordsArray count]) break;
NSString *str2 = [NSString stringwithformat#"%#", [allwordsArray objectAtIndex:counter]];
NSString *combinedStr = [NSString stringwithformat#"%# %#", str1,str2];
[twoWordArray addObject: combinedStr];
counter++;
}
You have broken the string into components, which is on the right track. You could then make a smaller array that only includes components until you reach the chunk size. The final step would be to rejoin the string.
NSArray *components = [self.textInput componentsSeparatedByString:#" "];
NSRange chunkRange = NSMakeRange(0, chunkSize);
NSArray *lessComponents = [components subarrayWithRange:chunkRange];
NSString *newString = [lessComponents componentsJoinedByString:#" "];

Out of the remaining numbers i wanted to choose some numbers but based on a certain counter variable whose value is randomly determined

I have an array that holds numbers from 1 to 7. Now i am selecting specific numbers and putting it on another subarray. If it doesn't contain those specific numbers i wanted to choose some numbers but based on a certain counter variable whose value is randomly determined. That is for example if counter value is 2 only two numbers from the remaining array elements must be chosed.
This might be a simple question but i need help as i am a beginner to ios and objective c
thanks in advance
what i have tried is
int counter = (arc4random()%(4-1))+1
for(int i=0; i<[mainarray count];i++)
{
if([[[mainarray objectAtIndex:i] objectAtIndex:1] integerValue]==specificnum)
{
[subarray addObject:[mainarray objectAtIndex:i]];
}
else if(counter==1)
{
[subarray addObject:[mainarray objectAtIndex:i]];
}
}
i am actually stuck in the else part
I am here showing arrays with sample values. Try this
int counter = (arc4random()%(4-1))+1;
int specificnum = 4;
NSLog(#"Counter:%i ",counter);
NSArray *mainarray = [NSArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5",#"6",#"7", nil];
NSMutableArray *subarray = [[NSMutableArray alloc]init];
for(int i=0; i<[mainarray count];i++)
{
if([[mainarray objectAtIndex:i] integerValue]==specificnum)
{
[subarray addObject:[mainarray objectAtIndex:i]];
}
else if(counter!=0)
{
[subarray addObject:[mainarray objectAtIndex:i]];
counter--;
}
}
NSLog(#"Array: %#",subarray );
int[] mainarray;
int[] subarray;
//suppose you have moved some array elements from mainarray to subarray.
//find present array length of main array
int main_length=mainarray.length();
int subarray_length=subarray.length();
Random rand = new Random();
int counter== rand.nextInt(main_length) + 1;
for(int i=0;i<counter;i++)
{
subarray[subarray_length]=mainarray[counter];
subarray_length++
}

Appending a string inside for loop crashes ios device

I'm gathering data to an array in string format and one item is about 30 characters. When data collection is finished I try to combine all the strings into one big string, which is then written to a file. Combining strings is done inside for-loop, and it causes device to crash when number of data items gets somewhere over 4000. What is causing it and how to fix? Here's the code I have for appending strings:
NSString *content = #"";
for (int i=0; i<self.log.count; i++)
{
content = [[content stringByAppendingString:#""] stringByAppendingString:(self.log)[i]];
}
If you are trying to turn an array into a string there is an easier way to do it:
NSString *content = [self.log componentsJoinedByString:#" "];
try this...
NSString *content = #"";
for (int i=0; i<self.log.count; i++)
{
content = [[content stringByAppendingString:#""] stringByAppendingString:[NSString stringWithFormat:#"%#",(self.log)[i]]];
}
To ensure the required amount of memory is allocated, I suggest you use a mutable string with an init for the length required.
-(NSString*)concantString:(NSArray *)incomingLog {
int calculatedLength = 0;
for (int i=0; i < [incomingLog count]; i++)
{
calculatedLength += [incomingLog[i] length];
}
NSMutableString *content = [[NSMutableString alloc] initWithCapacity:calculatedLength];
for (int i=0; i < [incomingLog count]; i++)
{
content = (NSMutableString*)[[content stringByAppendingString:#""] stringByAppendingString:incomingLog[i] ] ;
}
return content;
}

stringByAppendingString not concatenating

I'm trying to take an array of strings and take each item and put it into a string format. I wrote a method to do this as I need to concatenate the listed array values into another string. For some reason I cannot get the array values to list properly, a blank string is returned.
- (NSString*)listParameters:(NSArray*)params
{
NSString *outputList = #"";
if (params) {
for (int i=0; i<[params count]; i++) {
NSLog(#"%#",[params objectAtIndex:i]);
[outputList stringByAppendingString:[params objectAtIndex:i]];
if (i < ([params count] - 1)) {
[outputList stringByAppendingString:#", "];
}
}
}
NSLog(#"outputList: %#", outputList);
return outputList;
}
The first log statement properly returns a string (so there is definitely a string in the array), but the second log statement only returns "outputList: ".
I tried making outputList start as more than just an empty string which didn't work. I also tried assigning [params objectAtIndex:i] to a string then appending it, didn't work either.
I feel like I'm missing something obvious here, but I cannot get it to work.
How can I get this array of strings to print into a single string separated by commas?
You probably want to use a NSMutableString instead with its appendString method. NSString is immutable.
- (NSString*)listParameters:(NSArray*)params
{
NSMutableString *outputList = [[NSMutableString alloc] init];
if (params) {
for (int i=0; i<[params count]; i++) {
NSLog(#"%#",[params objectAtIndex:i]);
[outputList appendString:[params objectAtIndex:i]];
if (i < ([params count] - 1)) {
[outputList appendString:#", "];
}
}
}
NSLog(#"outputList: %#", outputList);
return outputList;
}
You need to assign the result of [outputList stringByAppendingString:[params objectAtIndex:i]] and [outputList stringByAppendingString:#", "] back to outputList.
It would be better still if you were using an instance of NSMutableString for outputList instead, as you're going to create a lot of autoreleased objects in that loop otherwise.
Try:
outputList = [outputList stringByAppendingString:#", "];
as stringByAppendingString works by returning a new String

Resources