MACollectionUtilities 是一组受 Smalltalk 启发的 Cocoa 集合类方法宏,利用了 blocks。该库在 BSD 许可下发布。
MACollectionUtilities 包含三个宏,用于简化创建数组、集合和字典。这些宏提供与其他语言中找到的集合字面量相似的功能,而不是 Cocoa 提供的难以管理的 [NSArray arrayWithObjects:...]
语法。
ARRAY(a, b, c)
- 创建一个包含对象 a、b 和 c 的 NSArray
。SET(a, b, c)
- 与 ARRAY
类似,但创建一个 NSSet
。DICT(a, b, c, d)
- 创建一个包含 a -> b
和 c -> d
的 NSDictionary
。请注意,DICT
使用我认为更合理的键/值顺序,而不是 Cocoa 的标准值/键顺序。请注意。
另外,请注意,这些宏不需要,您也不应放置一个 nil
,它们可以在没有您帮助的情况下检测其参数的结尾。
为 NSArray
和 NSSet
提供了方法,用于执行映射、过滤和匹配。在 NSArray
上使用时,结果数组与原始数组顺序相同,并且匹配总是找到第一个对象。NSSet
是无序的,因此结果也是无序的,并且找到的匹配对象是未定义的。这些分类方法的名称以 ma_
开头,以避免与其他分类方法冲突。
ma_map:
- 对集合中的每个对象调用块一次,并使用返回值创建一个新的集合。注意,块 不得 返回 nil
。ma_select:
- 对集合中的每个对象调用块一次。使用其中块返回 YES
的对象来创建一个新的集合。ma_match:
- 在集合中搜索对象,对于该对象的块返回 YES
,并返回它。ma_reduce:block:
- 使用第一个参数作为累积值开始。对数组的每个元素调用块,传递该元素到目前为止的累积值。将累积值设置为结果。允许在对数组执行任意“求和”操作。ma_sorted:
- 将块用作比较器来排序数组。与内置的 Cocoa 方法不同,比较器返回单个 BOOL
,表示两个对象是否应该按升序排序。请注意,这与正常 Cocoa 返回升序、降序或相等的常规技术不同。由于这种差异,比较器将比标准 Cocoa 方法更频繁地被调用,因为有时它需要调用两次才能完全检测到一对对象的排序。为了简化上述方法的使用,提供了辅助宏。这些宏将集合作为第一个参数,将表达式作为第二个参数。表达式用于创建一个块,该块被传递给适当的方法。大多数宏隐式创建参数 obj
,并可以在表达式中使用以引用单个对象。
MAP
、SELECT
和 MATCH
宏均对应于同名方法。REJECT
宏与 SELECT
相似,但选择表达式为 false 的对象。REDUCE
宏接受三个参数:集合、初始值和用于简化的表达式。此宏隐式创建参数 a
(累加值)和 b
(从数组中的对象)。SORTED
宏隐式创建参数 a
和 b
,并且第二个参数应该是当 a
应在 b
前排序时评估为 true 的表达式。取一个字符串数组并附加后缀
NSArray *newArray = MAP(stringArray, [obj stringByAppendingString: suffix]);
而不是附加前缀
NSArray *newArray = MAP(stringArray, [prefix stringByAppendingString: obj]);
在目录中查找文本文件
NSArray *files = SELECT([[NSFileManager defaultManager] contentsOfDirectoryAtPath: path error: NULL],
[[obj pathExtension] isEqual: @"txt"]);
查找图像文件
NSSet *extensions = SET(@"jpg", @"jpeg", @"tiff", @"png", @"pdf");
NSArray *files = SELECT([[NSFileManager defaultManager] contentsOfDirectoryAtPath: path error: NULL],
[extensions containsObject: [obj pathExtension]]);
找到以星号开头的第一个字符串
NSString *asteriskString = MATCH(stringArray, [obj hasPrefix: @"*"]);
连接数组中的所有字符串
NSString *concatenated = REDUCE(stringArray, @"", [a stringByAppendingString: b]);
计算数组中所有字符串长度的总和
NSNumber *sumObj = REDUCE(stringArray, nil, [NSNumber numberWithInteger: [a integerValue] + [b length]]);
NSUInteger sum = [sumObj integerValue];
按字符串长度升序排序字符串数组
NSArray *orderedArray = SORTED(array, [a length] < [b length]);
有时同时处理多个数组很有用。例如,假设你有两个字符串数组,并且你想创建一个包含两个数组内容合并成一个字符串的第三个数组。使用 MACollectionUtilities 进行此操作非常简单。
NSArray *first = ARRAY(@"alpha", @"air", @"bicy");
NSArray *second = ARRAY(@"bet", @"plane", @"cle");
NSArray *words = MAP(first, [obj stringByAppendingString: EACH(second)]);
// words now contains alphabet, airplane, bicycle
EACH
宏依赖于由其他宏设置的上下文。您 只能 与宏一起使用它,而不是与方法一起使用。
您可以使用多个数组与多个 EACH
宏并行枚举多个集合
NSArray *result = MAP(objects, [obj performSelector: NSSelectorFromString(EACH(selectorNames))
withObject: EACH(firstArguments)
withObject: EACH(secondArguments)];
EACH
宏通过内部创建和跟踪一个 NSEnumerator
来工作。它在第一次使用时懒惰地创建枚举器,然后在每次调用时使用 nextObject
。因此,如果您的数组长度不同,它将开始返回 nil
,请注意。
由于它们是无序的,并行枚举对于 NSSet
没有意义,并且不对其支持 EACH
。