How to convert valueForKeyPath in swift - objective-c

My old function in objective c is
+ (NSUInteger)getNumberOfDistinctUsers:(NSArray *)users {
NSArray* usersAfterPredicate = [users valueForKeyPath:#"#distinctUnionOfObjects.userName"];
return [usersAfterPredicate count]; }
How do I convert this in swift, I was trying to something like this but its crashing "Could not cast value of type 'Swift.Array'to 'Swift.AnyObject'"
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
var retval : Int = 0
if let usersAfterPredicate = (users as! AnyObject).valueForKeyPath("#distinctUnionOfObjects.userName") {
retval = usersAfterPredicate.count
}
return retval
}
Can I solve this problem using filter, map or Reduce? I am just trying to find out distint users in users array using the property username.
Edit* brute force way
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
var retvalSet : Set<String> = []
for user in users {
retvalSet.insert(user.userName)
}
return retvalSet.count
}

As you suspect, you can simplify the code with a simple map:
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
return Set(users.lazy.map{$0.userName}).count
}
This uses the fact that you can initialize a Set using any other sequence.
I added lazy in there to avoid creating an extra copy of the array. It'll work with or without, but I expect it to be much more memory efficient this way. Array.map creates another Array. array.lazy.map return a lazy collection that computes values as requested.
That said, I don't know that my approach is dramatically better than your "brute-force" way. It's not obvious which is easer to read or maintain. I have a fondness for the map approach, but it can be a tradeoff (I had to know to add lazy for instance, or I could have allocated significant memory if this were a large array). Your code makes it very clear what's going on, so I don't think there's any problem that has to be solved there.
If you really wanted to use KVC, you'd need to convert your array to an NSArray, not an AnyObject, but I suspect that the above code is much faster, and is clearer and simpler, too, IMO.

Related

Solidity: Dedupping string keys inside a pure function

I am trying to define a mapping to use inside a function as a means of quickly determining whether a key exists. I realize I could also use an array and loop thorugh it but that seems like it might get expensive. But that you can't create mappings dynamically, and if I create a state variable for the purpose, then I have the problem of clearing state between calls to this function which makes it pricey.
Here is what I was tyring to do, any suggestions for the most efficient method to dedupe a set of strings inside a pure function?
function dedupe(string[] memory keys) public pure returns(string[] memory) {
string[] memory deduped;
mapping(string=>bool) map;
string memory ikey;
for(uint i=0; i<keys.length; i++) {
ikey = keys[i];
if (!map[ikey]) {
map[ikey]=true;
deduped.push(ikey);
}
}
return deduped;
}

I'm curious about the speed difference between Kotlin's toList and IntArray

I was curious to see what Kotlin's toList is returned in, so I tested it.
fun loop(i: Int){
for(i in 0..i){}
}
fun main() {
val list: List<Int> = (1..100000).toList()
val arr = IntArray(100000) { i -> i}
println("list : ForLoop Time: " + measureNanoTime {
for (i in list) { loop(i) }
})
println("list : ForEach Time: " + measureNanoTime {
list.forEach { i -> loop(i) }
})
println("Array : ForLoop Time: " + measureNanoTime {
for (i in arr) { loop(i) }
})
println("Array : ForEach Time: " + measureNanoTime {
arr.forEach { i-> loop(i) }
})
}
output :
When I looked up, toList was returned in the form of an Array, but I don't know why there is a lot of difference in speed. Is toList returned as a LinkedList?
I wonder.
As Tenfour04 points out, microbenchmarks like this are subject to so many influences from JVM warm-up, dynamic compilation and profiling, system and timing jitter, cache effects, and other confounding factors that they don't tell you very much at all.  Benchmarking small bits of code is notoriously difficult, so far better to use a framework which has done all the hard work for you.
However, it seems fairly likely that one of the effects you're seeing here is that of boxing.
An IntArray is an array of (primitive) integers.
A List<Int> is a list (probably stored as an array) of references to Int objects, each of which holds a primitive integer.
So the list needs to store not just an array, but also all the individual Int objects; as a result, it'll take much more memory — probably several times more.
And while the array version does a simple linear scan through its memory (probably benefitting from memory caching), the list version will be accessing all the individual Int objects (which could be at unpredictable places in the heap) as well as scanning through its array of references, probably getting much less benefit from memory caching.
If you wanted a fairer comparison, you'd probably find that an Array<Int> behaved much more like a List<Int>.  (This is not to recommend using an Array<Int> in general, of course — this question illustrates one good reason why not!)

Passing and recieving multi-dimensional primitive (int) arrays in objective-c

I have two objective c methods. One needs to return an int[][] and the other which needs to take int[][] as a parameter. I was originally using an NSMutableArray with NSMutableArrays as values however I was told to redo it like this in order to be compatible with some current code. I can't figure out how to make this work. I'm not sure I'm even googling the right thing. Anyway here is what I have now.
+(int [][consantValue]) getCoefficients
{
int coefficiennts [constantValue2][constantValue1] = { {0,1,2}, {3,4,5}, {6,7,8} };
return coefficients;
}
At the return statement I get the Error "Array initilizer must be an initializer list'
I also have to take the int[][] and rebuild it into an NSMutableArray of NSMutableArrays in another method but I'm hoping if someone can give me a hint on the first part I can work the second part out myself although if anyone has any advice on that I would appreciate it as well. Thanks.
The easy way to do this for fixed size array(s) is to use a struct for storage:
typedef struct {
int at[constantValue2][constantValue1];
} t_mon_coefficients;
And then you'd declare the method which returns by value:
+ (t_mon_coefficients)coefficients;
And passes by value as a parameter:
- (void)setCoefficients:(const t_mon_coefficients)pCoefficients;
If the struct is large, you should pass by reference:
// you'd use this like:
// t_mon_coefficients coef;
// [SomeClass getCoefficients:&coef];
+ (void)getCoefficients:(t_mon_coefficients* const)pOutCoefficients;
- (void)setCoefficients:(const t_mon_coefficients*)pCoefficients;
But there are multiple ways one could accomplish this.

How to avoid if else or switch case whe dealing with enums?

I have a member variable that tells units for a value I have measured like centimeters,kilometers,seconds,hours etc.
Now these are enums,
When I display a corresponding string, I have created a method that returns corresponding string for these enums.
Unlike Java, enums here cant have other properties associated with them.
So I have to explicitly do a if-else-if chain or a switch case to return the correct string.
I am new to Objective C. any good practice that I should be following in such scenarios ?
afaik Objective-C enums are just old-school C enums... so maybe you can use an integer value for them?
I guess if your enum values started at 0 and increased you could use some sort of array access:
const char *distanceUnitToString2(enum DistanceUnit unit)
{
const char *values[] = {
"cm",
"m",
"km"
};
// do some sanity checking here
// ...
return values[unit];
}
But this feels a little flaky to me. What if you have negative values, or you are using bitmask-style enum values like 1 << 8? You are going to end up using a very large array.
You also could use a switch and improve it a little with a macro. Something like this:
const char *distanceUnitToString(enum DistanceUnit unit)
{
#define CASE(UNIT, STRING) case (UNIT): return (STRING)
switch (unit) {
CASE(kCentimeters, "cm");
CASE(kMeters, "m");
CASE(kKiloMeters, "km");
default:
// should not get here
assert(0);
break;
}
#undef CASE
}
But you don't really save that much vs. not using the macro.
Martin James's comment is the right answer. And use a definition of the enum like:
enum units { cm = 0, m, km };
that way you can be sure that your enum translates to the correct index values.

Casting a basic CFTypeRef to a more specific CoreFoundation type

Is there a simple way to convert a CTypeRef to a specific CoreFoundation type? I'm not looking to cast inline as (CFStringRef)myObjectRef but would like to create a helper method to do this for me for all CoreFoundation types.
I know it's possible to use something like CFGetTypeID(myObjectRef) == CFStringGetTypeID() to find out whether a CTypeRef is a CFString. However creating a single method to do this could become very verbose and have a lot of if statements.
Is building out a method with a bunch of if statements against CFGetTypeID() the only way? Or is there a simpler way to do this?
UPDATE: with example
I'd like to make a helper function to work with some legacy code I can't change. Currently it produces one of CFDictionaryRef, CFStringRef or CFURLRef as a return value provided as a CTypeRef. I'm currently working around this by running CFGetTypeID() on the returned value but this isn't ideal. Rather than having C-style casts all over the place, I'd rather have a CastToCF() helper which handles this for me. This would help make testing easier in the future as well.
P.S. I'm not worried about mutable types.
there's no obvious point in doing this. a c style cast is not like other languages - it is a typecast which the address on the left will be identical to the address on the right. cftypes will not throw or return null if you do a bad cast (unlike other languages). iow, it's merely a decoration for you to specify a type, and a c compiler will assume your cast is valid.
or perhaps you can provide a better example of how you would use this, if that did not help.
Update
ok. since you tagged it objc++, i'd just create a helper class which had plenty of diagnostics and did all the noisy conversions (minimal illustration):
class t_helper {
public:
t_helper(CFTypeRef cf) : d_cf(cf), d_type(CFGetTypeID(cf)) { assert(this->d_cf); }
~t_helper() {}
/* type info */
bool isString() const { return CFStringGetTypeID() == this->type(); }
CFStringRef string() { assert(this->isString()); return this->cf_cast<CFStringRef>(); }
bool isDictionary() const { return CFDictionaryGetTypeID() == this->type(); }
CFDictionaryRef dictionary() { assert(this->isDictionary()); return this->cf_cast<CFDictionaryRef>(); }
...
/* and a trivial example of an operation */
void appendMutableCopyToArray(CFMutableArrayRef array) {
if (this->isString()) {
CFMutableStringRef cp(CFStringCreateMutableCopy(0,0,this->string()));
CFArrayAppendValue(array, cp);
CFRelease(cp);
}
...
}
...
private:
template < typename T > T cf_cast() { return reinterpret_cast<T>(this->d_cf); }
const CFTypeID type() const { return this->d_type; }
private:
CFTypeRef d_cf;
const CFTypeID d_type;
};
that's about as accurate as i can get get without a really specific example of the program you are dealing with.