Skip to content

Commit

Permalink
CPDictionary key methods
Browse files Browse the repository at this point in the history
keysOfEntriesPassingTest:
keysOfEntriesWithOptions:passingTest:
keysSortedByValueUsingComparator:
  • Loading branch information
Aparajita Fishman committed Jul 15, 2012
1 parent dec7ca1 commit c4dc9c8
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 13 deletions.
83 changes: 70 additions & 13 deletions Foundation/CPDictionary.j
Expand Up @@ -25,6 +25,7 @@
@import "CPException.j"
@import "CPNull.j"
@import "CPObject.j"
#import "Ref.h"

/* @ignore */
@implementation _CPDictionaryValueEnumerator : CPEnumerator
Expand Down Expand Up @@ -359,30 +360,86 @@
var count = _keys.length,
index = 0,
matchingKeys = [],
thisKey = nil,
thisValue = nil;
key = nil,
value = nil;

for (; index < count; ++index)
{
thisKey = _keys[index];
thisValue = _buckets[thisKey];
if (thisValue.isa && anObject && anObject.isa && [thisValue respondsToSelector:@selector(isEqual:)] && [thisValue isEqual:anObject])
matchingKeys.push(thisKey);
else if (thisValue === anObject)
matchingKeys.push(thisKey);
key = _keys[index];
value = _buckets[key];

if (value.isa && anObject && anObject.isa && [value respondsToSelector:@selector(isEqual:)] && [value isEqual:anObject])
matchingKeys.push(key);
else if (value === anObject)
matchingKeys.push(key);
}

return matchingKeys;
}

- (CPArray)keysOfEntriesPassingTest:(Function /*(id key, id obj, @ref BOOL stop)*/)predicate
{
return [self keysOfEntriesWithOptions:CPEnumerationNormal passingTest:predicate];
}

- (CPArray)keysOfEntriesWithOptions:(CPEnumerationOptions)options passingTest:(Function /*(id key, id obj, @ref BOOL stop)*/)predicate
{
if (options & CPEnumerationReverse)
{
var index = [_keys count] - 1,
stop = -1,
increment = -1;
}
else
{
var index = 0,
stop = [_keys count],
increment = 1;
}

var matchingKeys = [],
key = nil,
value = nil,
shouldStop = NO,
stopRef = AT_REF(shouldStop);

for (; index !== stop; index += increment)
{
key = _keys[index];
value = _buckets[key];

if (predicate(key, value, stopRef))
matchingKeys.push(key);

if (shouldStop)
break;
}

return matchingKeys;
}

- (CPArray)keysSortedByValueUsingComparator:(Function /*(id obj1, id obj2)*/)comparator
{
return [[self allKeys] sortedArrayUsingFunction:function(a, b)
{
a = [self objectForKey:a];
b = [self objectForKey:b];

return comparator(a, b);
}
];
}

- (CPArray)keysSortedByValueUsingSelector:(SEL)theSelector
{
return [[self allKeys] sortedArrayUsingFunction:function(a, b) {
a = [self objectForKey:a];
b = [self objectForKey:b];
return [[self allKeys] sortedArrayUsingFunction:function(a, b)
{
a = [self objectForKey:a];
b = [self objectForKey:b];

return [a performSelector:theSelector withObject:b];
}];
return [a performSelector:theSelector withObject:b];
}
];
}

/*!
Expand Down
111 changes: 111 additions & 0 deletions Tests/Foundation/CPDictionaryTest.j
Expand Up @@ -206,6 +206,77 @@
}];
}

- (void)testKeysOfEntriesPassingTest
{
var numberDictionary = [CPDictionary dictionaryWithJSObject:{
key1: 5,
key2: 1,
key3: 4,
key4: 2,
key5: 3
}];

var expected = [@"key1", @"key3"],
result = [numberDictionary keysOfEntriesPassingTest:function(key, value, stop)
{
return value >= 4;
}];

[self assert:expected equals:result];

expected = [@"key3", @"key1"],
result = [numberDictionary keysOfEntriesWithOptions:CPEnumerationReverse passingTest:function(key, value, stop)
{
return value >= 4;
}];

[self assert:expected equals:result];

expected = [@"key3"],
result = [numberDictionary keysOfEntriesWithOptions:CPEnumerationReverse passingTest:function(key, value, stop)
{
if (value === 4)
stop(YES);

return value >= 4;
}];

[self assert:expected equals:result];

var stringDictionary = [CPDictionary dictionaryWithJSObject:{
a: @"Z", b: @"y", c: @"X", d: @"W",
e: @"V", f: @"u", g: @"T", h: @"s",
i: @"R", j: @"q", k: @"P", l: @"o"
}];

expected = [@"j", @"k", @"l"];
result = [stringDictionary keysOfEntriesPassingTest:function(key, value, stop)
{
return value.toLowerCase() <= @"q";
}];

[self assert:expected equals:result];

expected = [@"l", @"k", @"j"];
result = [stringDictionary keysOfEntriesWithOptions:CPEnumerationReverse passingTest:function(key, value, stop)
{
return value.toLowerCase() <= @"q";
}];

[self assert:expected equals:result];

expected = [@"j", @"k"];
result = [stringDictionary keysOfEntriesPassingTest:function(key, value, stop)
{
if (value === @"P")
stop(YES);

return value.toLowerCase() <= "q";
}];

[self assert:expected equals:result];
}

- (void)testKeysSortedByValueUsingSelector
{
var numberDictionary = [CPDictionary dictionaryWithJSObject:{
Expand Down Expand Up @@ -237,6 +308,46 @@
[self assert:expected equals:result];
}

- (void)testKeysSortedByValueUsingComparator
{
var numberDictionary = [CPDictionary dictionaryWithJSObject:{
key1: 5,
key2: 1,
key3: 4,
key4: 2,
key5: 3
}];

var expected = [@"key2", @"key4", @"key5", @"key3", @"key1"],
result = [numberDictionary keysSortedByValueUsingComparator:function(obj1, obj2)
{
return obj1 < obj2 ? CPOrderedAscending : CPOrderedDescending;
}];

[self assert:expected equals:result];

var stringDictionary = [CPDictionary dictionaryWithJSObject:{
a: @"Z", b: @"y", c: @"X", d: @"W",
e: @"V", f: @"u", g: @"T", h: @"s",
i: @"R", j: @"q", k: @"P", l: @"o"
}];

expected = [@"l", @"k", @"j", @"i", @"h", @"g", @"f", @"e", @"d", @"c", @"b", @"a"];
result = [stringDictionary keysSortedByValueUsingComparator:function(obj1, obj2)
{
return obj1.toLowerCase() < obj2.toLowerCase() ? CPOrderedAscending : CPOrderedDescending;
}];

[self assert:expected equals:result];

expected = [@"k", @"i", @"g", @"e", @"d", @"c", @"a", @"l", @"j", @"h", @"f", @"b"];
result = [stringDictionary keysSortedByValueUsingComparator:function(obj1, obj2)
{
return obj1 < obj2 ? CPOrderedAscending : CPOrderedDescending;
}];
[self assert:expected equals:result];
}

- (void)testJSObjectDescription
{
var dict = [[CPDictionary alloc] initWithObjects:[CGRectMake(1, 2, 3, 4), CGPointMake(5, 6)] forKeys:[@"key1", @"key2"]],
Expand Down

0 comments on commit c4dc9c8

Please sign in to comment.