【问题标题】:Initialize NSArray with floats?用浮点数初始化 NSArray?
【发布时间】:2009-10-05 09:49:19
【问题描述】:

这是用浮点对象初始化 NSArray 的有效方法吗?

NSArray *fatArray = [NSArray arrayWithObjects:
                    [NSNumber numberWithFloat:6.9],
                    [NSNumber numberWithFloat:4.7],
                    [NSNumber numberWithFloat:6.6],
                    [NSNumber numberWithFloat:6.9],nil];

它有效,感觉也不错,只是想确保我走在正确的轨道上。

加里

【问题讨论】:

    标签: objective-c cocoa


    【解决方案1】:

    正如 mouviciel 已经写的那样,这就是这样做的方法。当我写这样的东西时,我通常会使用一个简单的宏来缩短代码:

    #define FBOX(x) [NSNumber numberWithFloat:x]
    

    然后你可以像这样重写代码:

    NSArray *fatArray = [NSArray arrayWithObjects:
        FBOX(6.9), FBOX(4.7), FBOX(6.6), FBOX(6.9), nil];
    

    宏是邪恶的,但在这种情况下,宏是如此简单,我会使用它。此外,代码阅读起来也少了一点伤害,尤其是在宏定义不远的情况下。

    如果你写了很多这样的代码,你可以创建一个带有可变数量的float参数的自定义初始化器的类别,但是在结束参数列表时会出现问题。您可以先传递浮点总数:

    - (id) initWithFloats: (int) numFloats data: (float) float1, ...;
    

    但是手工计算参数很容易出错。或者您可以使用一些标记值(例如零)来标记参数列表的结尾,但这会打开一个全新的蠕虫罐,称为浮点比较。


    请注意,现在您可以简单地编写以下内容:

    NSArray *list = @[@6.9, @4.7, @6.6, @6.9];
    

    这不是语法梦想成真,但它得到了编译器的官方支持,并且比以前的解决方案要好得多。 See the documentation for more goodness.

    【讨论】:

    • 与 0.0 的比较没有问题,但这通常不是有用的哨兵值。不过,我喜欢宏观的想法。
    【解决方案2】:

    另一个懒惰的选择是只使用一个 NSStrings 数组,然后直接从字符串中获取您要查找的值的类型。

    像这样:

    NSArray *arrayOfNumbers = [NSArray arrayWithObjects:@"3.12",@"3.2", @"12", @"15", nil];
    float number = [[arrayOfNumbers objectAtIndex:0] floatValue];
    

    【讨论】:

      【解决方案3】:

      稍微有点切线,如果您只想存储一个浮点数组并且不需要 NSArray 或 NSNumber 的附加功能,那么您也应该只考虑一个标准 C 数组:

      float fatArray[] = {6.6, 6.9, 4.7, 6.9};
      

      【讨论】:

      • 当然,C 数组没有边界检查或引用计数,因此如果您编写一个涉及其中的错误,您不太可能很快发现它。
      • 是的,但是分配5个对象来存储4个浮点数似乎有点浪费。
      • NS 对象是保存在 NSUserDefaults 中所必需的。由于它们更复杂,如果不需要使用它们,那么 OP 将已经使用这里给出的更简单的构造。
      • 这无关紧要,不回答问题。
      【解决方案4】:

      据我所知,这是将浮点数放入 NSArray 的一种完全有效的方法。

      【讨论】:

        【解决方案5】:

        我同意 mouviciel 的观点。由于您不能将简单类型放入 Array 中,因此这是这样做的方法。看起来有点奇怪,要写很多代码但还好。

        【讨论】:

          【解决方案6】:

          如果您要创建大量具有完全相同数量的元素的数组,您可以定义一个 FloatArrayFactory 类来实现以下内容:

          + (NSArray *) arrayWithFloat: (float)f;
          + (NSArray *) arrayWithFloat: (float)f1 and: (float)f2;
          + (NSArray *) arrayWithFloat: (float)f1 and: (float)f2 and: (float)f3;
          + (NSArray *) arrayWithFloat: (float)f1 and: (float)f2 and: (float)f3 and: (float)f4;
          

          如果这太冗长,您可以使用未命名参数的简洁和时髦的外观:

          + (NSArray *) arr: (float)f1 : (float)f2 : (float)f3;
          

          你可以这样称呼它:

          NSArray *a = [Factory arr: 1.0 :2.0 :3.0 :4.0];
          

          【讨论】:

          • 或者不是工厂,而是一个类别(这就是他们发明的目的)
          • 其实我最初是把它写成一个类别的,但我认为向 NSArray 添加构造方法并不是那么有用。
          【解决方案7】:

          如果你有很多浮点数要转换,或者想从逗号分隔的列表中粘贴它们,调用将浮点数转换为 NSArray 实例的函数可能会更容易。

          NSArray*  arrayFromFloats(NSUInteger count, float *floats)
          {
              NSMutableArray* ma = [NSMutableArray arrayWithCapacity:count]; 
              NSUInteger i; 
              for (i=0; i<count; i++) { 
                  [ma addObject:[NSNumber numberWithFloat:floats[i]]];
              }
              return (NSArray*)ma; 
          }
          

          调用者示例:

          static float floats[] = {1.1, 2.2, 3.3}; 
          NSUInteger count = sizeof(floats)/sizeof(float);
          NSArray* a = arrayFromFloats(count, floats); 
          

          【讨论】:

          • 首先,既然没有理由传递否定的count,它应该是无符号的; int,没有其他限定,已签名。其次,它应该是 NSUInteger 而不是 (unsigned) int,以防万一你有超过 40 亿的 floats(可能在 64 位运行时)。
          • 谢谢你,彼得。我在示例代码中将int 更改为NSUInteger
          • 不同意 NSUInteger 而不是 unsigned int; unsigned int 是可以的,为什么不呢(并且 NSUInteger 可以unsigned int,我们不需要更多索引 ~4*10^9 元素,这对于很多应用程序来说已经足够了)跨度>
          猜你喜欢
          • 1970-01-01
          • 2010-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-29
          • 1970-01-01
          • 2012-02-29
          • 1970-01-01
          相关资源
          最近更新 更多