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 9 years ago.
Improve this question
Folks, I'm trying to do the following.
I've got a array (NSArray) called 'specialLevels', that array looks like this:
specialLevels = #[#2, #4, #6, #9];
This should be a array of int's.
I also got the int 'currentLevel' (basic int no object).
And I want to check if the currentLevel is in de array of specialLevels.
I know the method 'containsObject' exists, but this won't work in my case.
What would you guys recommend to do in this case?
So I thought this, but it feels kinda strange imo:
if ([specialLevels containsObject:[NSNumber numberWithInt:currentLevel]]) {
// other code in here
}
You could alternatively write:
if ([specialLevels containsObject:#(currentLevel)]) {
// other code in here
}
which is more in keeping with the style of your other code.
specialLevels is not an array of ints. It is an array of NSNumber objects. #2, #4, #6, #8 each create an NSNumber instance equivalent to calling [[NSNumber numberWithInt:value]. When you call containsObject you also need to pass an NSNumber object so that containsObject can match the value (using isEqual:).
You can read about Objective-C literals here.
Related
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
Trying to add the contents of an array together.
["75.00", "50.00", "25.00"] the way I'm getting that info is with
c = Credit.last
c.payments.map(&:payment_amount).to_a
I'm trying to add up all the values together in the array.
The other posters are correct in that your question doesn't conform to the how to ask guidelines. The responses are not intended to put you down but rather to maintain the quality of content for stack overflow. That said this should get you where you need to go. IN the future please read the guidelines and submit accordingly.
Credit.last.payments.sum(:payment_amount.to_f)
One thing you may not have considered is that the array ["75.00", "50.00", "25.00"] contains a bunch of strings.
If you were to sum them together like this:
["75.00", "50.00", "25.00"].sum
# or like this as one commenter suggested
["75.00", "50.00", "25.00"].reduce(&:+)
# or the long-handed version
["75.00", "50.00", "25.00"].reduce {|str, val| str + val }
You would actually get "75.0050.0025.00". This is because the individual strings in the array are getting concatenated together.
So in fact, you would need to convert the array to floats or integers first. This can be done like this:
floats = ["75.00", "50.00", "25.00"].collect(&:to_f)
# or the long-handed version
["75.00", "50.00", "25.00"].collect {|val| val.to_f }
Then you can sum the values:
sum = floats.sum
Edit:
I just tried summing a string column via ActiveRecord and got an exception ActiveRecord::StatementInvalid: TinyTds::Error: Operand data type nvarchar is invalid for sum operator.:.
payment_total = Credit.last.payments.sum(:payment_amount)
# returns ActiveRecord::StatementInvalid:
# TinyTds::Error: Operand data type nvarchar is invalid for sum
# operator.
Looks like that won't be an option for you. Although, you could change the datatype of the column so that it is something other than a string. If you change the column datatype then you will be able to use aggregate functions.
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 7 years ago.
Improve this question
Any tips to refactor this condition?
params = {:p1=>"foo", :p2=>true, :p3=>nil, :pN=>""}
if params[:p1].present? && params[:p2].present? && params[:pN].present?
# do something...
Something like this:
params.values_at(:p1, :p2, :pN).all?(&:present?)
if params.values_at(*%i[p1 p2 p3]).all?(&:present?)
values_at returns an Array of the values for each key you provide.
all? is true iff the predicate (present?) is true for every member of the enumerable. values_at will include nil for a missing key (rather than omit it), so you don't need to worry about the array collapsing down to only present values.
keys = [:p1, :p2, :pN]
puts "hi" if keys.all? { |k| params[k].present? }
This has the advantage of terminating the hash lookup as soon as params[k].present? is false.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Solution:
I have marked #BlackRider's answer as correct as it is the most versatile especially for complex comparisons however there are other very good answers and comments. I would encourage anyone with the same or similar question to review them and evaluate the best course of action for your specific situation.
In my situation, I am actually not using BlackRider's solution in my implementation. I have elected to use my own solution (see Edit #2 below) with help from #JoshCaswell's comments as well as #voromax's suggestion of indexesOfObjectsWithOptions:passingTest: due to the fact that my comparisons are very simple in this situation.
Thanks to everyone who answered and provided insight.
I am looking for an efficient way to retrieve an object from an NSArray based on a property of that object (a unique identifier, in this case). In C#.NET using Linq I would do something like
MyObject obj = myList.Single(o => o.uuid == myUUID);
I am also wondering if there is an efficient way to get an array of objects matching a non-unique property. Again, with Linq it would look like
List<MyObject> objs = myList.Where(o => o.flag == true).ToList();
Of course I can write loops to do this but they would not be reusable and I'm suspicious of their performance.
Finding an object with a unique ID:
-(MyObject*)findObjectWithUUID:(NSString*)searchUUID{
for (MyObject* obj in _myArray){
if([obj.uuid isEqualToString: searchUUID])
return obj;
}
}
Finding an array of objects:
-(NSArray*)findObjectsWithFlag:(BOOL)f{
NSMutableArray* arr = [NSMutableArray array];
for (MyObject* obj in _myArray){
if(obj.flag == f)
[arr addObject:obj];
}
return arr;
}
-- EDIT --
Luckily in the first situation the object I am looking for has a unique identifier and I know there will only be one. I came up with a solution to implement isEqual on my object which will be invoked by indexOfObject:
- (BOOL)isEqual:(id)object{
return [self.uuid isEqualToString: ((MyObject*)object).uuid];
}
And then create a "fake" lookup object and use that to find the real one
MyObject *lookupObject = [[MyObject alloc] init];
lookupObject.uuid = searchUUID;
MyObject *actualObject =
[_myArray objectAtIndex:[_myArray indexOfObject:lookupObject]];
This is essentially the same as the for-in loop I posted above, but might be more readable & be more reusable. Of course, this only works for finding one unique object and does not address the second half of my question.
-- EDIT 2 --
Checking Class and implementing hash as recommended in comments.
- (BOOL)isEqual:(id)object{
return [object isKindOfClass:[MyObject class]] &&
[self.uuid isEqualToString: ((MyObject*)object).uuid];
}
- (NSUInteger)hash{
return [self.uuid hash];
}
You can use [NSPredicate], which gives you a query-like syntax for search. Check out this page for the predicate syntax description. Here's a simple example:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"propertyName == %#", #"value"];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];
As to performance, I think your solution is OK since any search in an array needs to iterate through all the elements anyway, and then, for each object, compare the value of a field against the value you search for. You can optimize repeat searches within the same data, e.g. by creating and populating a dictionary that maps values of some field to the matching objects (or collections of objects, if the mapping is one to many).
You may also look at modern block syntax: indexOfObjectWithOptions:passingTest: or indexesOfObjectsWithOptions:passingTest: which support concurrency and search order.
I was intrigued by rmaddys comment so I've checked the difference between looping and predicate.
Let's assume a simple object with NSString property. I've inserted it into array 10 000 times , every time with different property value.
In the worst case scenario when desired object was on the last position of the array, loop approach was 3.5x faster than NSPredicate (0.39s vs 0.11s, arraySize = 10000, 10 iterations, iPad Mini)
Code I used for reference: pastebin
I know its related with NSArray but if we do it using Swift and using the swift Array which is a struct, then that will be lot easier.
Swift 2.2 / Swift 3.0 / Swift 4.x Working fine on all versions
Lets assume we have a custom model class
class User {
var userId = 0
var userName = ""
}
And lets assume we have an array named as usersArray which has custom objects of User class.
And we want to fetch an object from this array with userId = 100 for example:-
let filteredArray = usersArray.filter({$0.userId == 100})
This filtered array will contain all the custom objects which have userId as 100
print(filteredArray[0].userName) //will print the name of the user with userId = 100
just for those who are interested, I've found the fastest way to search through NSArray is by using a for loop on a background thread. using the [self performSelectorInBackground...] method.
In an NSArray of 10000 custom objects I searched through the whole thing thoroughly in around 1 second. On the main thread it took around 10 seconds or more.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I'm looking for the most efficient way to achieve the following task...
I have an array of Objects of type Foo, amongst other properties, Foo has a latitude and a longitude property. Given an array of many Foo's, I need to extract the Foo's with matching lat / long's into one new array.
I have implemented several solutions which are working, including iterating using a for loop, and a solution using an NSPredicate, but both of these methods involve multiple iterations through an array. This array could potentially have hundreds of thousands of records, so i'm looking for something i can use which will achieve the desired result in one pass.
EDIT: Adding some pseudo-code to describe the approach i've already taken and to better describe the problem...
NSMutableArray * matchingLocations = [[NSMutableArray alloc] initWithCapacity:0];
for (Foo * checkingFoo in fooArray) {
NSMutableArray * checkingArray = [NSArray arrayWithArray:fooArray];
[checkingArray removeObject:checkingFoo];
for (Foo * foo in checkingArray) {
// I have a method coded for comparing two coordinates
if (checkingFoo.coordinate == foo.coordinate) {
[matchingLocations addObject:checkingFoo];
}
}
}
NSSet will provide a collection of unique objects. In order to implement it properly however you need to define what does mean to be identical for the Foo object. You do that in your Foo class implementation rewriting the method isEqual: and the method hash.
In your Foo class:
- (BOOL)isEqual:(id)object {
return (self.coordinate == [(Foo *)object coordinate]);
}
- (NSUInteger)hash {
return ([self.coordinate hash]);
}
Then everywhere in your code you can just use:
NSArray *array; // Your array with multiple Foo objects potentiually duplicates
NSSet *set = [NSSet setWithArray:array];
Have a loo kat the Apple Documentation reference for:
[NSObject isEqual:] https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/isEqual:
[NSSet setWithArray:]
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSSet_Class/Reference/Reference.html#//apple_ref/occ/clm/NSSet/setWithArray:
You are running two fast enumeration as for loop of same array. Which is not correct. If you want to compare the co-ordinates then excecute for loop of different array. And also you can add directly to mutable array if same for loop only you are using.
If you want to compare objects from the array, then I suggest you use NSSet instead of NSArray.
It is very easy to use and the below link is something you want because I resolved such a case using NSMutableSet :
NSSet Tutorial
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 9 years ago.
Improve this question
I have two questions.
1) I need to create a dynamic structure, whose members are driven through an array.
For ex:
members = [:a, :b]
Config = Struct.new(members) #=> Struct.new(:a, :b)
FlatConfig = Struct.new(members) #=> Struct.new(:a, :b)
config = Config.new()
flat = FlatConfig.new()
After some days, If I need to add another member to these struct, then all I need to do is add a member in that members array (memebers = [:a, :b, :c]) and I don't need to tough the code further. Thus I am asking this. How to achieve this?
2) Now I need to build the values of flat Struct members by means of doing some manipulation on config struct member values.
For eg:
config.each{|configMember|
result = configMember.collect{|c| someArray.collect{|s| s + '--' + y}}
flat[":#{cofigMember}"] = result #=> Intent is to store result in same member as iterated through config struct.
}
How to achieve (1) and (2)?
Thanks in advance.
For your 1), use the splat operator:
Struct.new(*members)
I don't really understand your second question. Is "how can I access the same variable in two configs"?
config.members.each { |key|
configMember = config[key]
# do something
flat[key] = result
}