NSExpression

本文转自:NSHipster中文博客

每当涉及查询或者整理信息时,Cocoa总是其他标准库羡慕的对象。通过使用NSPredicateNSSortDescriptor,以及偶尔使用NSFetchRequest,即使是最复杂的数据任务也可以被简化成为几行极其容易读懂的代码。

现在,NSHipster们无疑已经熟悉NSPredicate 了(如果你还不熟悉,下周一定要过来看看),不过如果我们更进一步看看NSPredicate,我们会发现NSPredicate其实是由更小的部分而组成:两个NSExpression(一个左手值和一个右手值),和一个运算符相比较(比如<INLIKE等等)。

大多数开发者通过+predicateWithFormat:来使用NSPredicateNSExpression是一个相对难懂的类。真可惜啊,因为NSExpression本身的功能非常强大。

所以,亲爱的读者,请允许我来表达我对NSExpression深深的尊重和着迷:

评估数学

关于NSExpression你所要知道的第一件事就是它的主要目的是减少表达。如果你思考一下评估NSPredicate的过程,你会发现它有两个表达和一个比较符号,所以我们需要将两个表达简化为运算符可以处理的表达--非常像编译一行代码的过程。

这就是我们要学习的NSExpression的第一招: 做数学题

NSExpression *expression = [NSExpression expressionWithFormat:@"4 + 5 - 2**3"];
id value = [expression expressionValueWithObject:nil context:nil]; // => 1

这并不是Wolfram Alpha,但是如果加入评估数学表达式对于你的应用很有用的话,那么...你就可以使用NSExpression。

函数

我们仅仅触及了NSExpression的表面。觉得一台电脑仅仅做小学数学不怎么厉害?那高中的统计学怎么样?

NSArray *numbers = @[@1, @2, @3, @4, @4, @5, @9, @11];
NSExpression *expression = [NSExpression expressionForFunction:@"stddev:" arguments:@[[NSExpression expressionForConstantValue:numbers]]];
id value = [expression expressionValueWithObject:nil context:nil]; // => 3.21859...

NSExpression 函数以给定数目的子表达式作为参数。比如,在上述例子中,要得到集合的标准差,数列中的数字要被+expressionForConstantValue:封装。虽然只是一个小小的不便(它最终却能使得NSExpression变得极其灵活),却足以使第一次尝试它的人绊倒。

如果你觉得 键值编码简单集合运算符 (@avg@sum等等)不够用,也许NSExpression的自带的统计,算术和位运算功能能激起你的兴趣。

要注意的是根据Apple的NSExpression文档中的表格,很明显,Mac OS X & iOS的功能可用性之间没有重叠。看起来最近的iOS版本的确支持如stddev之类的函数,但这些变化并没有显示在头文件或者文档里。如果你注意到任何变化,请以pull request的形式告诉我,不胜感激。

统计

  • average:
  • sum:
  • count:
  • min:
  • max:
  • median:
  • mode:
  • stddev:

基本运算

这些函数需要用两个NSExpression对象来表达数字。

  • add:to:
  • from:subtract:
  • multiply:by:
  • divide:by:
  • modulus:by:
  • abs:

高级运算

  • sqrt:
  • log:
  • ln:
  • raise:toPower:
  • exp:

边界函数

  • ceiling: - (不小于数组中的值的最小积分值)
  • trunc: - (最接近但不大于数组中的值的积分值)

math.h函数类似的函数

ceiling非常容易和ceil(3)混淆。ceiling作用于数字数组,而ceil(3)作用于一个double值(且它并没对应的内置NSExpression函数)。floor:在这里的作用和floor(3)一样。

  • floor:

随即函数

两个变量--一个带参数,一个不带参数。不带参数时,random返回rand(3)的等值,而random:则从NSExpression的数字数组中取任意元素。

  • random
  • random:

二进制运算

  • bitwiseAnd:with:
  • bitwiseOr:with:
  • bitwiseXor:with:
  • leftshift:by:
  • rightshift:by:
  • onesComplement:

日期函数

  • now

字符串函数

  • lowercase:
  • uppercase:

空操作

  • noindex:

自定义函数

除了这些内置的函数,你也可以在NSExpression中调用自定义函数。由Dave DeLong所撰写的这篇文章 详述了这个过程。

首先,在类别中定义一个对应的函数:

@interface NSNumber (Factorial)
- (NSNumber *)factorial;
@end

@implementation NSNumber (Factorial)
- (NSNumber *)factorial {
    return @(tgamma([self doubleValue] + 1));
}
@end

然后,这样使用函数(+expressionWithFormat: 中的FUNCTION()宏是构造-expressionForFunction:等等的过程的简写。):

NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(4.2, 'factorial')"];
id value = [expression expressionValueWithObject:nil context:nil]; // 32.578...

这样的优势在于, 通过直接调用-factorial,我们可以调用NSPredicate查询中的函数。比如,我们可以定义一个location:withinRadius:方法来轻松的查询用户当前位置附近的管理对象。

正如Dave在他的文章中所提到的那样,这些用例十分边缘化,但它们肯定可以成为你的保留节目中有趣的技巧。.

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 今天给大家分享一个关于C#自定义字符串替换方法的实例,希望能对大家有所帮助。具体介绍如下: 之前我遇到了一个算法题,题目要求将一个字符串中的某些片段替换为指定的新字符串片段。例如,对于源字符串“abcdeabcdfbcdefg”,需要将其中的“cde”替换为“12345”,最终得到的结果字符串是“ab12345abcdfb12345fg”,即从“abcdeabcdfbcdefg”变为“ab12345abcdfb12345fg”。 经过分析,我发现不能直接使用C#自带的string.Replace方法来实现这个功能。于是,我决定自定义一个方法来完成这个任务。这个方法的参数包括:原始字符串originalString、需要被替换的字符串片段strToBeReplaced以及用于替换的新字符串片段newString。 在实现过程中,我首先遍历原始字符串,查找需要被替换的字符串片段strToBeReplaced出现的位置。找到后,就将其替换为新字符串片段newString。需要注意的是,在替换过程中,要确保替换操作不会影响后续的查找和替换,避免遗漏或重复替换的情况发生。 以下是实现代码的大概逻辑: 初始化一个空的字符串result,用于存储最终替换后的结果。 使用IndexOf方法在原始字符串中查找strToBeReplaced的位置。 如果找到了,就将originalString中从开头到strToBeReplaced出现位置之前的部分,以及newString拼接到result中,然后将originalString的查找范围更新为strToBeReplaced之后的部分。 如果没有找到,就直接将剩余的originalString拼接到result中。 重复上述步骤,直到originalStr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值