NSArray.all
Invokes the given block for each element in the receiver. Should the
block return NO
, the method immediately returns NO
, ceasing
enumeration. If all executions of the block return YES
, all
returns YES
.
BOOL rv = @[@1, @2, @3].all(^(id o){
return [o intValue] > 0;
});
// rv => YES
BOOL rv = @[@1, @2, @3].all(^(int d){
return d < 3;
});
// rv => NO
Instead of a block, you can pass a Class
object.
BOOL rv = @[@1, @2, @3].all(NSNumber.class);
// rv => YES
NSArray.any
BOOL rv = @[@1, @2, @3].any(^(id o){
return [o intValue] == 3;
});
// rv => YES
Instead of a block, you can pass a Class
object.
BOOL rv = @[@1, @2, @3].any(NSNumber.class);
// rv => YES
NSArray.chunk
Chunks the receiver into a new array of chunk-size arrays.
id rv = @[@1, @2, @3, @4].chunk(2)
// rv => @[@[@1, @2], @[@3, @4]]
NSArray.concat
Returns a new array that is the receiver with the given array
concatenated to the end.
id rv = @[@1, @2].concat(@[@3, @4]);
// rv => @[@1, @2, @3, @4]
NSArray.dict
Convert an array of key/value pairs into the logical dictionary.
id rv = @[@[@1, @2], @[@3, @4]].dict
// rv => @{@1: @2, @3: @4}
id rv = @[@1, @2, @3, @4].chunk(2).dict
// rv => @{@1: @2, @3: @4}
If you have a flat array you can call chunk(2)
before dict
. It was
decided not to allow flat arrays to be immediately converted as it can
lead to bugs when your array is not in the shape you expect, and those
sorts of errors occur more commonly with tools like YOLOKit since we
allow easy array flattening.
NSArray.each
Calls the given block once for each element in the receiver, passing
that element as the parameter.
@[@1, @2, @3, @4].each(^(id n){
NSLog(@"%@", n);
});
// => 1\n2\n3\n4\n
each
also supports two and three parameter versions:
@[@4, @3, @2, @1].each(^(id n, int ii){
NSLog(@"%d:%@", ii, n);
});
// => 0:1\n1:2\n2:3\n3:4\n
@[@4, @3, @2, @1].each(^(id n, int ii, NSArray *array){
//…
});
@[@4, @3, @2, @1].each(^(id n, NSNumber *index, NSArray *array){
// and automagical conversion between int and NSNumber
});
NSArray.find
Passes each entry in the array to the given block, returning the first
element for which block is not NO
. If no object matches, returns
nil
.
id rv = @[@1, @2, @3, @4].find(^(id n){
return [n isEqual:@3];
});
// rv => @3
NSArray.first
Returns the first n
elements of the receiver.
id rv = @[@1, @2, @3, @4, @5, @6].first(2);
// rv => @[@1, @2]
PROTIP YOLOKit is forgiving; if the array doesn’t have enough elements,
`first` returns as many as it can.
NSArray.flatten
Returns a new, one-dimensional array that is a recursive flattening of
the receiver.
id rv = @[@[@1, @[@2]], @3, @[@4]].flatten
// rv => @[@1, @2, @3, @4]
NSArray.flatMap
Returns a new array with the concatenated results of running block once
for every element in the receiver.
id rv = @[@1, @2, @3, @4].flatMap(^(id n){
return @[n, n];
});
// rv => @[@1, @1, @2, @2, @3, @3, @4, @4]
id rv = @[@1, @2, @3, @4].flatMap(^(id n){
return @[n, @[n]];
});
// rv => @[@1, @[@1], @2, @[@2], @3, @[@3], @4, @[@4]]
PROTIP Useful over vanilla map followed by a flatten because flatten is
recursive, and you may want to preserve array relationships beyond the
first level. Also, `flatMap` is technically more efficient.
NSArray.groupBy
Groups the collection by result of the given block.
id rv = @[@1, @2, @3, @4].groupBy(^(NSNumber *n) {
return @(n.intValue % 2);
});
// rv => @{@0: @[@1, @3], @1: @[@2, @4]}
NSArray.has
BOOL rv = @[@1, @2, @3].has(@2)
// rv => YES
Short-hand for containsObject:. Provided because doing a map, then a
select and a few more chained dot-notations are commonly followed with
the need to then determine if a particular value is in the resulting
array, and then having to square bracket the whole chain is ugly.
We decided not to override any or find with the capability to take an
object rather than a block and instead add this method. Rest assured the
decision was careful. In the end has() seemed the choice that resulted in
the clearest code.
has
was chosen over contains or includes because it is short and
clear.
NSArray.indexOf
Returns the index of the given object in the receiver or NSNotFound
if
the object was not found.
uint rv = @[@1, @2, @3, @4].indexOf(@2);
// rv => 1
PROTIP `NSNotFound` has the value `NSIntegerMax` so you don’t need to
directly check for it, you can instead check if the returned value is
less than the count of the receiver.
NSArray.inject
Combines all elements of the receiver by applying a binary operation.
id rv = @[@1, @2, @3, @4].inject(@{}, ^(NSMutableDictionary *memo, NSNumber *n){
memo[n] = @(n.intValue * n.intValue);
return memo;
});
// rv => @{@1: @1, @2: @4, @3: @9, @4: @16}
PROTIP If you feed `inject` a non-mutable dictionary or array YOLOKit
mutates it for your block, and then finally returns a non-mutable copy.
NSArray.join
Returns a string of all the receiver’s elements joined with the provided
separator string.
id rv = @[@1, @2, @3, @4].join(@",");
// rv => @"1,2,3,4"
id rv = @[@1, @2, @3, @4].join(@"");
// rv => @"1234"
PROTIP `-description` is called on all objects before joining them.
NSArray.last
Returns the last n
elements from receiver.
id rv = @[@1, @2, @3, @4, @5, @6].last(2);
// rv => @[@5, @6]
PROTIP If there are insufficient elements in the array, YOLOKit returns
as many as it can.
NSArray.map
Invokes the given block once for each element of self. Creates a new
array containing the values returned by the block.
id rv = @[@1, @2, @3, @4].map(^(NSNumber *n){
return @(n.intValue * n.intValue);
});
// rv => @[@1, @4, @9, @16]
If the given block returns nil, that element is skipped in the returned
array.
The given block can have up to three parameters, the first is an element
in the array, the second that element’s index, and the third the array
itself.
The second parameter can be a primitive (eg. int
), or an NSNumber *
:
@"YOLO".split(@"").map(^(NSString *letter, int index){
//…
});
NSArray.max
Returns the element for which the given block returns the largest
integer.
id rv = @[@4, @2, @1, @3].max(^(NSNumber *n){
return n.intValue;
});
// rv => @4
id rv = @[@4, @2, @1, @3].max(^(NSNumber *n){
return (n.intValue - 3) * (n.intValue - 3);
});
// rv => @1
NOTE: currently you must return an integer, we plan to allow you to
return whatever you like.
NSArray.min
Returns the element for which the given block returns the smallest
integer.
id rv = @[@4, @2, @1, @3].min(^(NSNumber *n){
return n;
});
// rv => @1
NOTE: currently you must return an integer, we plan to allow you to
return whatever you like.
NSArray.none
BOOL rv = @[@1, @2, @3].none(^(id o){
return [o intValue] > 4;
});
// rv => YES
Instead of a block, you can pass a Class
object.
BOOL rv = @[@1, @2, @3].none(NSNumber.class);
// rv => NO
NSArray.partition
Partitions the receiver into two arrays based on the boolean return
value of the given block.
id rv = @[@"A", @"B", @"AA"].partition(^(id s){
return [s hasPrefix:@"A"];
});
//rv => @[@[@"A", @"AA"], @[@"B"]]
NSArray.pluck
Returns a new array that is the result of calling the given method on
each element in the receiver.
MKShape *rhombas = [MKShape new]; rhombas.title = @"rhombas";
MKShape *ellipse = [MKShape new]; ellipse.title = @"ellipse";
MKShape *hexagon = [MKShape new]; hexagon.title = @"hexagon";
id rv = @[rhombas, ellipse, hexagon].pluck(@"title")
// rv => @[@"rhombas", @"ellipse", @"hexagon"]
id rv = @[rhombas, ellipse, hexagon].pluck(@"title.uppercaseString")
// rv => @[@"RHOMBAS", @"ELLIPSE", @"HEXAGON"]
NOTE: This is a convenience function for the common case of mapping
(-map
) an array to the result of a method call on each element.
NSArray.pmap
Map, but run in parallel. Obviously: be thread safe in your block. The
call waits for all elements to be processed. Typically not worth using
unless you have large arrays since the overhead of
thread-synchronization may be greater than the parallel savings
otherwise.
NSArray.reduce
Reduces the receiver to a single value.
The usual example of reduce is to sum all values in an array.
id rv = @[@1, @2, @3, @4].reduce(^(NSNumber *memo, NSNumber *obj){
return @(memo.intValue + obj.intValue);
});
// rv => @10
Generally -inject
is more useful. Though, when appropriate, reduce
is more elegant.
// find the longest word
id longest = @[@"cat", @"sheep", @"bear"].reduce(^(NSString *memo, NSString *word){
return memo.length > word.length ? memo : word;
});
// longest => @"sheep"
@param memo initialized to the first value in receiver, but on subsequent iterations is the value returned from the given block.
@param obj the value for each element in the receiver, though never the first object.
NSArray.reject
Returns a new array containing all elements for which the given block
returns NO
.
id rv = @[@1, @2, @3, @4].reject(^(NSNumber *n){
return n.intValue % 2 == 0;
});
// rv => @[@1, @3]
Alternatively pass a Class
object:
id rv = @[@1, @"1", @{}].reject(NSNumber.class)
// rv => @[@"1", @{}]
NSArray.reverse
Returns a new array that is the receiver, reversed.
id rv = @[@1, @2, @3, @4].reverse;
// rv => @[@4, @3, @2, @1]
NOTE: Did you know about array.reverseEnumerator.allObjects
? We don’t
use that in fact to save allocations, but you could do that on projects
without YOLOKit.
NSArray.rotate
Returns a new array rotated about the provided index.
id rv = @[@1, @2, @3, @4, @5, @6].rotate(2);
// rv => @[@3, @4, @5, @6, @1, @2]
id rv = @[@1, @2, @3, @4, @5, @6].rotate(-2);
// rv => @[@5, @6, @1, @2, @3, @4]
NSArray.sample
Returns a random element from the receiver.
NSArray.select
Returns a new array containing all elements for which the given block
returns YES
.
id rv = @[@1, @2, @3, @4].select(^(NSNumber *n){
return n.intValue % 2 == 0;
});
// rv => @[@2, @4]
Alternatively pass a Class
object:
id rv = @[@1, @"1", @{}].select(NSString.class)
// rv => @[@"1"]
Convenient when searching for specifc subviews.
self.view.subviews.select(UITextField.class);
Though you may need an allSubviews
pod.
NSArray.shuffle
Returns a new array that is shuffled.
NOTE: Uses the Fisher–Yates shuffle algorithm.
NSArray.skip
Skips the first n
elements and returns the rest of the array.
id rv = @[@1, @2, @3, @4, @5, @6].skip(2);
// rv => @[@3, @4, @5, @6]
NSArray.slice
Returns a subarray consisting of the given number of elements from the
given starting index.
id rv = @[@1, @2, @3, @4, @5, @6].slice(2, 2));
// rv => @[@3, @4]
PROTIP Use slice instead of `first`, `last`, `skip` and `snip`… when
you must. If you find yourself writing `array.slice(0, 4)` then consider
`array.first(4)` instead: it’s more expressive, more explicit and
shorter to boot.
NSArray.snip
Snips the end off the array. Returns the receiver without the last n
elements.
id rv = @[@1, @2, @3, @4, @5, @6].snip(2);
// rv => @[@1, @2, @3, @4]
NSArray.sort
Returns the receiver, sorted.
id rv = @[@2, @1, @3, @5, @4].sort;
// rv => @[@1, @2, @3, @4, @5]
We even try to handle mixed object types:
id rv = @[@"20", @"1", @3, @5, @"4"].sort;
// rv => @[@"1", @3, @"4", @5, @"20"]
PROTIP Internally `sort` attempts to sort all objects using `-compare:`
but if that fails, it calls `-description` on all objects and uses
`-sortBy`.
NSArray.sortBy
Sorts all objects using the return value of the given block as the
sorting criteria.
MKShape *rhombas = [MKShape new]; rhombas.title = @"rhombas";
MKShape *ellipse = [MKShape new]; ellipse.title = @"ellipse";
MKShape *hexagon = [MKShape new]; hexagon.title = @"hexagon";
id rv = @[rhombas, ellipse, hexagon].sortBy(^(id shape){
return [shape title];
});
// rv => @[ellipse, hexagon, rhombas]
id rv = @[rhombas, ellipse, hexagon].sortBy(@"title")
// rv => @[ellipse, hexagon, rhombas]
id rv = @[
@{@"name": @"frank", @"age": @32},
@{@"name": @"frank", @"age": @31},
@{@"name": @"bob", @"age": @54},
@{@"name": @"zane", @"age": @1},
@{@"name": @"frank", @"age": @12}
].sortBy(^(id o){
return @[o[@"name"], o[@"age"]];
});
// rv => @[
// @{@"name": @"bob", @"age": @54},
// @{@"name": @"frank", @"age": @12},
// @{@"name": @"frank", @"age": @31},
// @{@"name": @"frank", @"age": @32},
// @{@"name": @"zane", @"age": @1}
// ];
PROTIP You will need you to implement a compare: method for any custom
objects you return.
PROTIP Returning an array from your block will sort the receiver so
that the first object is the first sorting criteria, and the second
object is the second sorting criteria, et cetera.
NSArray.transpose
Assumes that the receiver is an array of arrays and transposes the rows
and columns.
id rv = @[@[@1, @2, @3], @[@4, @5, @6]].transpose;
// rv => @[@[@1, @4], @[@2, @5], @[@3, @6]]
PROTIP `transpose` is surprisingly useful, if you think laterally about
your problem.
NSArray.uniq
Returns a new array by removing duplicate values in the receiver.
id rv = @[@1, @1, @2].uniq;
// rv => @[@1, @2]
PROTIP Order is preserved.
PROTIP Equality is determined via `-hash` and `-isEqual:`.
NSArray.without
Returns a new array where objects in the given array are removed from
the receiver.
id rv = @[@1, @2, @3, @4, @5, @6].without(@2);
// rv => @[@1, @3, @4, @5, @6]
id rv = @[@1, @2, @3, @4, @5, @6].without(@[@2, @3]);
// rv => @[@1, @4, @5, @6]