I'm trying to use an if statement to work out which of 2 strings comes first alphabetically. Like with numbers and greater and less than:
if (1 < 2) {
just with strings:
if(#"ahello" < #"bhello") {
Or would I have to have a string containing all the letters and then check the index of the first char in each string and see which index is greater, and the index that is less than the other comes first in the alphabet and then if they are equal move on to the next char and repeat?
What you can do is:
NSString *stringOne = #"abcdef";
NSString *stringTwo = #"defabc";
NSComparisonResult result = [stringOne compare:stringTwo];
if (result == NSOrderedAscending) // stringOne < stringTwo
...
if (result == NSOrderedDescending) // stringOne > stringTwo
...
if (result == NSOrderedSame) // stringOne == stringTwo
...
There are also other methods for performing different kinds of comparisons (such as case-insensitivity, diacritic insensitivity, etc), but the result of the comparison can still be treated like the above. Alternatively, some people find it easier to compare result to 0. The operator used to compare result to 0 would be the same operator used in other languages where string comparisons can be done directly:
if (result < 0) // stringOne < stringTwo
...
if (result > 0) // stringOne > stringTwo
...
if (result == 0) // stringOne == stringTwo
...
Most (if not all) of the compare:... methods of NSString are wrappers for compare:options:range:locale:. The different kinds of options that you can pass can be found here.
NSString has a whole slew of compare: methods to do just what you want. Some are very simple, and others have a bunch of options you can use to customise the behaviour. Check out the documentation.
Related
Can't seem to figure out how to check a string so that the same two characters in a row are not allowed.
I don't want anyone to be able to submit data with "00".
What about just:
(\d)\1+
The \d matches any digit and the \1+ matches whatever was matched in the first bit when it appears more than one time.
Pertaining to your comments though, it's much easier just to check:
if ([expiryDate rangeOfString:#"00"].location != NSNotFound)
{
//Invalid date
}
or even perhaps more validating:
NSArray *components = [expiryDate componentsSeparatedByString:#"/"];
int month = [components[0] intValue];
int year = [components[1] intValue];
NSAssert(month > 0 && month <= 12, #"Invalid Month");
NSAssert(year >= 13 /*current year*/ /* (optionally) && year < 20 (or some other future year)*/, #"Invalid year");
I want to put a bunch of buttons on the screen that correspond with an array slot.
For example, buttonA corresponds to myArray[3][28].
Would I have to have a ton of else-if statements like this:
else if (x == 3 && y == 28)
//"it's buttonQ" code
else if (x == 3 && y == 29)
//"it's buttonR" code
or is there a better way?
Note: x is the "horizontal" index of the 2D array myArray, while y is its "vertical" index
I think it is feasible to devise a scheme where you can use the position as part of your data scheme. It seems to me that this is what you are doing anyway because you are relating the horizontal coordinates to letters in the alphabet.
So you could do for example something like this:
NSString *letters = #"ABCDEFGHIJKLMNOPQRSTUVXYZ";
...
else if (x == 3) {
NSString *letter = [NSString stringWithFormat:#"%c"
[letters characterAtIndex:y-11]];
// use letter in your code
}
...
Similarly, you could device code that takes into account the row as well in a more complex matrix of buttons.
Often in my code I need to check whether the state of x amount of bools are all true OR all bools are false. So I do:
BOOL first, second, third;
if((first && second && third) || (!first && !second && !third))
//do something
Being a lazy programmer, I want to know if there is some mathematical shorthand for this kind of query, instead of having to type out this whole thing every time?
The shorthand for all bools the same is testing for (pairwise) equality:
(first==second && second==third)
Of course you can expand this to any number of booleans, having N-1 equality checks joined with the and operator.
If this is something you frequently require then you're better off using an integer and reading bits individually.
For instance, instead of:
BOOL x; // not this
BOOL y; // not this
BOOL z; // not this
...and instead of bit fields (because their layout is implementation-defined):
unsigned int x : 1; // not this
unsigned int y : 1; // not this
unsigned int z : 1; // not this
...use a single field such as:
unsigned int flags; // do this
...and assign every value to a bit; for example:
enum { // do this
FLAG_X = (1 << 0),
FLAG_Y = (1 << 1),
FLAG_Z = (1 << 2),
ALL_FLAGS = 0x07 // "all bits are on"
};
Then, to test "all false" you simply say "if (!flags)" and to test "all true" you simply say "if (flags == ALL_FLAGS)" where ALL_FLAGS is a number that sets all valid bits to 1. Other bitwise operators can be used to set or test individual bits as needed.
Note that this technique has an upper limit of 32 Boolean values before you have to do more (e.g. create an additional integer field to store more bits).
Check if the sum is 0 or equal to the number of bools:
((first + second + third) % 3 == 0)
This works for any number of arguments.
(But don't take this answer serious and do it for real.)
When speaking about predicates, you can usually simplify the logic by using two variables for the quantification operations - universal quantification (for all) and existential quantification (there exists).
BOOL allValues = (value1 && value2 && value3);
BOOL anyValue = (value1 || value2 || value3);
if (allValues || !anyValue) {
... do something
}
This would also work if you have a lot of boolean values in an array - you could create a for cycle evaluating the two variables.
Coming from an extremely spoiled family upbringing (turbo pascal, python, ruby) I'm a bit puzzled when it comes to doing all the household chores myself.
Yesterday was one of these days where I just did not find myself a solution. I had to check whether a value matches one of some other values.
x = some_function_return_value();
if x in (1,4,17,29,35):
That's how I used to write it. Now with Objective-C I obviously can't do that. And I searched the old google, but found no answer, and the old manual, and nothing there, so how do you do this in Objective-C, without doing something cranky like the following?
if (x == 1 || x == 4 || x == 17 || x == ...) {
Edited: in this case it is an (int), I know for NSArray and NSString there are methods for this
If it's about integer values, you can use switch:
switch (x) {
case 1:
case 4:
case 17:
case 29:
case 35:
do_something();
break;
}
Do not forget that in C/C++/Objective-C, the cases fall through to the next by default. You need to add break; statements to prevent that.
For non-integer values, you have to do long if statements with a lot of repetition as C doesn't provide syntactic sugar or features that many scripting languages have to abbreviate this.
Another way would be for example to prepare an array and then do:
if ([myArray containsObject:[NSNumber numberWithInteger:x]])
or even better, use an NSSet for that. This will work for most objects, for example it will also work with strings.
There is a fast enumeration syntax in objective C that uses "in" to loop over collections, however given it requires converting your int values to NSNumbers, it's probably easier to use C here
BOOL success = NO;
int size = 5
NSInteger numbers[size] = {1,4,17,29,35};
for (int i = 0; i < size; i++) {
if (yourValue == numbers[i]) {
success = YES;
break;
}
}
if (success) {
/* do your stuff */
}
admittedly not as nice as python...
Here's my silly program of the day:
bool int_exists_in_array(const int n, const int a[], const size_t elementCount) {
return (0 != elementCount) &&
(n == a[0] || int_exists_in_array(n, a + 1, elementCount - 1U));
}
so this:
if x in (1,4,17,29,35):
becomes:
const int a[] = { 1, 4, 17, 29, 35 };
if (int_exists_in_array(x, a, sizeof(a)/sizeof(a[0]))) {
...
}
You can use NSSet in addition with NSValue.
I'm implementing some custom NSArray sort selectors and I was wondering whether there's anything like the <=> operator in C/Objective-C?
I have this:
if (self.count == otherObject.count) return 0;
return (self.count > otherObject.count)? 1 : -1;
and would love to have (as in Perl)
return self.count <=> otherObject.count;
Maybe the compare: method is what you are looking for? NSString, NSNumber etc implement it. All compare-like methods in Cocoa returns a NSComparisonResult:
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
So you can use the returned integer value directly. Assuming that count in your question is a NSNumber you can do:
return [self.count compare:otherObject.count];
If your case is limited to numbers and you want to use just an operator you can probably use good old minus. But be aware of integer overflow!:
return self.count - otherObject.count;
It's called the Spaceship Operator and it originated in Perl; besides Perl, only Ruby and Groovy have it.
Not in C, and probably not in Objective-C.
You could write a function easily enough, though it would be specific to a particular operand type:
int compare(int x, int y) {
return x < y ? -1 : (x > y);
}
Or you could write a macro, which could be applied to any type with <, ==, and > operators, but it would sometimes evaluate its arguments more than once:
#define COMPARE(x, y) ((x) < (y) ? -1 : ((x) > (y)))
(Note that both versions depend on the > operator yielding 0 for false, 1 for true.)