http://underscorem.org/
https://github.com/robb/Underscore.m
Underscore.m
a functional toolbelt for Objective-C
Underscore.m is a small utility library to facilitate working with common data structures in Objective-C.
It tries to encourage chaining by eschewing the square bracket]]]]]].
It is inspired by the awesome underscore.js. Underscore.m was written by Robert Böhnke and is MIT licensed.
Underscore.m on GitHubExamples
Consider these Hello World! strings:
NSDictionary *dictionary = @{
@"en": @"Hello world!",
@"sv": @"Hej världen!",
@"de": @"Hallo Welt!",
@"ja": [NSNull null]
}
Underscore.m makes extracting the strings and capitalizing them a breeze.
NSArray *capitalized = Underscore.dict(dictionary)
.values
.filter(Underscore.isString)
.map(^NSString *(NSString *string) {
return [string capitalizedString];
})
.unwrap;
Underscore.m is especially useful when you deal with structured data from web APIs.
NSArray *tweets = Underscore.array(results)
// Let's make sure that we only operate on NSDictionaries, you never
// know with these APIs ;-)
.filter(Underscore.isDictionary)
// Remove all tweets that are in English
.reject(^BOOL (NSDictionary *tweet) {
return [tweet[@"iso_language_code"] isEqualToString:@"en"];
})
// Create a simple string representation for every tweet
.map(^NSString *(NSDictionary *tweet) {
NSString *name = tweet[@"from_user_name"];
NSString *text = tweet[@"text"];
return [NSString stringWithFormat:@"%@: %@", name, text];
})
.unwrap;
Installation
It is recommended to use CocoaPods to install Underscore.m. Alternatively you can download the code from GitHub.
You may want to alias Underscore to _ to make accessing Underscore.m’s methods more concise.
#import "Underscore.h"
#define _ Underscore
NSArray
The following methods can be used with NSArray and NSMutableArray instances. With Underscore.m’s array methods can use a functional-style syntax as well as chaining to create powerful expressions.
Underscore.m supports the following methods to manipulate arrays:
arrayUnderscore.array(NSArray *array)
Wraps an array in an USArrayWrapper. Use this method if you want to chain multiple operations together. You will need to call unwrap to extract the new array at the end.
NSArray *elements = Underscore.array(array)
.flatten
.uniq
.unwrap;
Since array is meant for chaining, you probably don’t need to keep a reference to the USArrayWrapper.
unwrapwrapper.unwrap
Extracts the array of an USArrayWrapper.
firstUnderscore.first(NSArray *array)
Returns the first element of the array or nil if it is empty.
id first = Underscore.first(array);
lastUnderscore.last(NSArray *array)
Returns the last element of the array or nil if it is empty.
id last = Underscore.last(array);
headUnderscore.head(NSArray *array, NSUInteger n)
Returns the first n elements or all of them, if there are less than n elements in the array.
NSArray *firstThree = Underscore.head(array, 3);
tailUnderscore.tail(NSArray *array, NSUInteger n)
Returns the last n elements or all of them, if there are less than n elements in the array.
NSArray *lastThree = Underscore.tail(array, 3);
indexOfUnderscore.indexOf(NSArray *array, id obj)
Returns the index of the first occurrence of obj in array or NSNotFound, if the element could not be found.
NSUInteger twentySix = Underscore.indexOf(alphabet, @"z");
flattenUnderscore.flatten(NSArray *array)
Recursively flattens the array.
NSArray *arrayOfArrays = @[ @[ @1, @2], @[ @3, @4], @[ @5, @6] ];
NSArray *oneToSix = Underscore.flatten(arrayOfArrays);
withoutUnderscore.without(NSArray *array, NSArray *values)
Returns all elements not contained in values.
NSArray *oddNumbers = Underscore.without(allNumbers, evenNumbers);
shuffleUnderscore.shuffle(NSArray *array)
Shuffles the array using the Fisher-Yates-Shuffle.
NSArray *shuffled = Underscore.shuffle(array);
reduceUnderscore.reduce(id memo, UnderscoreReduceBlock block)
reduceRightUnderscore.reduceRight(id memo, UnderscoreReduceBlock block)
Reduces the array to a single value using the block.
NSArray *numbers = @[ @1, @2, @3, @4, @5, @6, @7 ];
NSArray *sum = Underscore.array(numbers)
.reduce(@0, ^(NSNumber *x, NSNumber *y) {
return @(x.integerValue + y.integerValue);
})
.unwrap;
eachwrapper.each(UnderscoreArrayIteratorBlock block)
arrayEachUnderscore.arrayEach(NSArray *array, UnderscoreArrayIteratorBlock block)
Calls block once with every member of the array. This method returns the same array again, to facilitate chaining.
Functional syntax:
Underscore.arrayEach(objects, ^(id obj) {
NSLog(@"%@", obj);
});
Chaining:
Underscore.array(objects)
.each(^(id obj) {
NSLog(@"%@", obj);
});
mapwrapper.map(UnderscoreArrayMapBlock block)
arrayMapUnderscore.arrayMap(NSArray *array, UnderscoreArrayMapBlock block)
Calls block once with every element of the array. If the block returns nil, the object is removed from the array. Otherwise, the return-value replaces the object.
Functional syntax:
Underscore.arrayMap(strings, ^(NSString *string) {
return string.capitalizedString;
});
Chaining:
Underscore.array(strings)
.map(^(NSString *string) {
return string.capitalizedString;
});
pluckUnderscore.pluck(NSArray *array, NSString *keyPath)
Returns an array containing the objects’ values for the given key path.
NSArray *names = Underscore.pluck(users, @"name");
uniqUnderscore.uniq(NSArray *array)
Returns a new array containing all elements of array exactly once.
NSArray *uniques = Underscore.uniq(@[ @1, @1, @2, @3 ]);
findUnderscore.find(NSArray *array, UnderscoreTestBlock test)
Returns an object from the array the passes the test or nil, if none of the elements match.
User *admin = Underscore.find(users, ^BOOL (User *user) {
return user.isAdmin;
})
filterUnderscore.filter(NSArray *array, UnderscoreTestBlock test)
Returns all elements that pass the test.
NSArray *dictionaries = Underscore.filter(objects, Underscore.isDictionary);
rejectUnderscore.reject(NSArray *array, UnderscoreTestBlock test)
Returns all elements that fail the test.
NSArray *dictionaries = Underscore.reject(objects, Underscore.isNull);
allUnderscore.all(NSArray *array, UnderscoreTestBlock test)
Returns YES if all elements pass the test.
BOOL onlyStrings = Underscore.all(objets, Underscore.isString);
anyUnderscore.any(NSArray *array, UnderscoreTestBlock test)
Returns YES if any of the elements pass the test.
BOOL containsNull = Underscore.any(objets, Underscore.isNull);
NSDictionary
The following methods can be used with NSDictionary and NSMutableDictionaryinstances. With Underscore.m’s dictionary methods can use a functional-style syntax as well as chaining to create powerful expressions.
Underscore.m supports the following methods to manipulate dictionaries:
dictUnderscore.dict(NSDictionary *dictionary)
Wraps a dictionary in an USDictionaryWrapper. Use this method if you want to chain multiple operations together. You will need to call unwrap to extract the result.
NSDictionary *user = Underscore.dict(data)
.rejectValues(Underscore.isNull)
.defaults(@{
@"avatar": kDefaultAvatar,
@"backgroundColor": kDefaultBackgroundColor
})
.unwrap;
Since dict is meant for chaining, you probably don’t need to keep a reference to theUSDictionaryWrapper.
unwrapwrapper.unwrap
Extracts the dictionary of an USDictionaryWrapper.
keysUnderscore.keys(NSDictionary *dictionary)
Returns the keys of a dictionary.
NSArray *keys = Underscore.keys(dictionary);
When called on a USDictionaryWrapper, it returns a USArrayWrapper to facilitate chaining.
id key = Underscore.dict(dictionary)
.keys
.first;
valuesUnderscore.values(NSDictionary *dictionary)
Returns the values of a dictionary.
NSArray *values = Underscore.values(dictionary);
When called on a USDictionaryWrapper, it returns a USArrayWrapper to facilitate chaining.
id value = Underscore.dict(dictionary)
.values
.first;
eachwrapper.each(UnderscoreDictionaryIteratorBlock block)
dictEachUnderscore.each(NSDictionary *dictionary, UnderscoreDictionaryIteratorBlock block)
Calls block once with every key-value pair of the dictionary. This method returns the same dictionary again, to facilitate chaining.
Functional syntax:
Underscore.dictEach(dictionary, ^(id key, id obj) {
NSLog(@"%@: %@", key, obj);
});
Chaining:
Underscore.dict(objects)
.each(^(id key, id obj) {
NSLog(@"%@: %@", key, obj);
});
mapwrapper.map(UnderscoreDictionaryMapBlock block)
dictMapUnderscore.map(NSDictionary *dictionary, UnderscoreDictionaryMapBlock block)
Calls block once with every key-value pair of he dictionary. If the block returns nil, the key-value-pair is removed from the dictionary. Otherwise, the return-value replaces the value.
Functional syntax:
Underscore.dictMap(dictionary, ^(id key, id obj) {
if ([obj isKindOfClass:NSString.class]) {
return [(NSString *)obj capitalizedString]
} else {
return obj;
});
Chaining:
Underscore.dict(dictionary)
.map(^(id key, id obj) {
if ([obj isKindOfClass:NSString.class]) {
return [(NSString *)obj capitalizedString]
} else {
return obj;
}
});
pickUnderscore.pick(NSDictionary *dictionary, NSArray *keys)
Returns a copy of dictionary that contains only the keys contained in keys.
NSDictionary *subset = Underscore.pick(info, @[ @"name", @"email", @"address" ]);
extendUnderscore.extend(NSDictionary *destination, NSDictionary *source)
Returns a dictionary that contains a union of key-value-pairs of destination andsource. Key-value-pairs of source will have precedence over those taken fromdestination.
NSDictionary *dictionary = Underscore.extend(user, @{ @"age": @50 });
defaultsUnderscore.defaults(NSDictionary *dictionary, NSDictionary *defaults)
Returns a dictionary that contains a union of key-value-pairs of dictionary anddefaults. Key-value-pairs of destination will have precedence over those taken fromdefaults.
NSDictionary *dictionary = Underscore.defaults(user, @{ @"avatar": kDefaultAvatar });
A common use case for defaults is sanitizing data with known values.
NSDictionary *user = Underscore.dict(data)
.rejectValues(Underscore.isNull)
.defaults(@{
@"avatar": kDefaultAvatar,
@"backgroundColor": kDefaultBackgroundColor
})
.unwrap;
filterKeysUnderscore.filterKeys(NSDictionary *dictionary, UnderscoreTestBlock test)
Returns a dictionary that only contains the key-value-pairs whose keys pass test.
NSDictionary *soundcloudRelated = Underscore.filterKeys(data, ^BOOL (NSString *key) {
return [key hasPrefix:@"soundcloud-"];
});
filterValuesUnderscore.filterValues(NSDictionary *dictionary, UnderscoreTestBlock test)
Returns a dictionary that only contains the key-value-pairse whose values passtest.
NSDictionary *numericValues = Underscore.filterValues(data, Underscore.isNumber);
rejectKeysUnderscore.rejectKeys(NSDictionary *dictionary, UnderscoreTestBlock test)
Returns a dictionary that only contains the key-value-pairs whose keys fail test.
NSDictionary *safe = Underscore.rejectKeys(data, ^BOOL (NSString *key) {
return [blackList containsObject:key];
});
rejectValuesUnderscore.rejectValues(NSDictionary *dictionary, UnderscoreTestBlock test)
Returns a dictionary that only contains the key-value-pairs whose values fail test.
NSDictionary *noNulls = Underscore.rejectValues(data, Underscore.isNull);
Helpers
negateUnderscore.negate(UnderscoreTestBlock block)
Returns a block that negates block
id notNull = Underscore.find(array, Underscore.negate(Underscore.isNull));
isEqualUnderscore.isEqual(id obj)
Returns a block that returns YES whenever it is called with an object equal to obj.
BOOL containsNeedle = Underscore.any(haystack, Underscore.isEqual(@"needle"));
isArrayUnderscore.isArray
A block that returns YES if it is called with an NSArray.
isDictionaryUnderscore.isDictionary
A block that returns YES if it is called with an NSDictionary.
isNullUnderscore.isNull
A block that returns YES if it is called with an NSNull.
isNumberUnderscore.isNumber
A block that returns YES if it is called with an NSNumber.
isStringUnderscore.isString
A block that returns YES if it is called with an NSString.
Underscore.m是一个Objective-C小型实用程序库,用于简化常见数据结构的操作。它支持数组和字典的各种处理方法,如筛选、映射、归约等,并提供一系列辅助函数来帮助开发者更高效地进行开发。
733

被折叠的 条评论
为什么被折叠?



