NSMutableString到NSMutableArray

时间:2013-12-23 23:12:46

标签: objective-c nsstring nsmutablearray

我有一个带有一堆浮点数的NSMutableString

我需要将它们转换为NSMutableArray,但需要转换为3个小组:

  

0.015637 0.0205293 0.0270841 0.0157598 0.0202236 0.0272967 0.013217 0.0205293 0.0283439 0.0115028 0.0205293 0.0290539 0.0107803 0.0202236 0.0296187 -0.029892 0.0194995 0.0108798 -0.0299242 0.0191089 0.0108915 0.0243682 0.0194995 0.0204474 0.0307989 0.0205293 -0.00543068 0.0313996 0.0202236 0.00274711 -0.0157598 0.0202236 0.0272967 -0.0180789 0.0202236 0.0258193 -0.0182457 0.0194995 -0.0260576 - 0.0182654 0.0191089 -0.0260857 -0.0134582 0.0191089

这些数字都是浮点值,可能超过30 000或更多。

我试过这个,但它不起作用......

NSArray *contentarray = [content componentsSeparatedByString: @" "];

for(NSNumber * withfastenumeration in contentarray)
{
    [XYZarray addObject: withfastenumeration];
}

嗨,大家好,

我想在这个问题上添加更多信息,因为你们一直都很有帮助。好的,这是一个基于COLLADA XML的项目,它涉及向量,因此有大量的浮点数。

我到了解析NSXMLParser并分离点的地步。但是,它们在XML文件中以空白格式重复排列为X,Y,Z,仅用空格分隔。

我正在编写一个加工算法,所以我需要在数组中使用这些数字,但我需要数组看起来像:

X0.015637 Y0.0205293 Z0.0270841 X0.0157598 Y0.0202236 Z0.0272967

一旦我拥有了,那么我就能以类似的方式操纵所有这些数字。

再次感谢这些解决方案和节日快乐!

3 个答案:

答案 0 :(得分:3)

componentsSeparatedByString:会返回NSString的数组,而不是NSNumber的数组。您需要编写代码以将每个组件转换为数字。例如,您可以向每个组件发送doubleValue以获取double,然后使用@(...)double包裹在NSNumber中。

NSArray *words = [content componentsSeparatedByString:@" "];
NSMutableArray *triples = [NSMutableArray arrayWithCapacity:words.count / 3];
for (NSUInteger i = 0, count = words.count; i < count; i += 3) {
    NSArray *triple = @[
        @([words[i+0] doubleValue]),
        @([words[i+1] doubleValue]),
        @([words[i+2] doubleValue])
    ];
    [triples addObject:triple];
}

请注意,-[NSString doubleValue]不会进行区域设置感知解析。如果您需要,则需要使用NSScannerNSNumberFormatter。此外,如果您在使用30000+子串数组所使用的内存时遇到问题,请使用NSScanner一次处理一个子字符串,而不创建大数组。

以下是NSScanner

的使用方法
NSScanner *scanner = [NSScanner scannerWithString:content];
// or use localizedScannerWithString: for locale-aware parsing

NSMutableArray *triples = [NSMutableArray arrayWithCapacity:words.count / 3];

double x, y, z;
while ([scanner scanDouble:&x] && [scanner scanDouble:&y] && [scanner scanDouble:&z])  {
    NSArray *triple = @[ @(x), @(y), @(z) ];
    [triples addObject:triple];
}

答案 1 :(得分:2)

第一个想法

这是怎么回事?

NSMutableString *_string = // your raw string as in your question...
NSLock *_lock = [[NSLock alloc] init];
NSMutableArray *_array = [NSMutableArray array];
[[_string componentsSeparatedByString:@" "] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([_lock tryLock]) [_array addObject:@([obj doubleValue])], [_lock unlock];
}];

第二个想法

如果你想优雅地使用3组中的数字,那将是一个更好的解决方案:


将这些内容放在 .h 文件中:

typedef struct {
    Float64 a;
    Float64 b;
    Float64 c;
} FloatNumbers;

static inline FloatNumbers FloatNumbersMake(Float64 a, Float64 b, Float64 c) {
    FloatNumbers fn; fn.a = a; fn.b = b; fn.c = c; return fn;
}

static inline NSString * NSStringFromFloatNumbers(FloatNumbers fn) {
    return [NSString stringWithFormat:@"{%f, %f, %f}", fn.a, fn.b, fn.c];
}

static inline FloatNumbers FloatNumbersFromString(NSString * string) {
    @try {
        NSArray *_array = [[string stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"{}"]] componentsSeparatedByString:@", "];
        return FloatNumbersMake([[_array objectAtIndex:0] doubleValue], [[_array objectAtIndex:1] doubleValue], [[_array objectAtIndex:2] doubleValue]);
    }
    @catch (NSException *exception) {
        return FloatNumbersMake(0.f, 0.f, 0.f);
    }
}

以及 .m 文件的任何方法(您要解析原始字符串):

NSMutableString *_string = // your raw string with the numbers...
NSError *_error;
NSLock *_lock = [[NSLock alloc] init];
NSMutableArray *_mutableArray = [NSMutableArray array];
NSRegularExpression *_regExp = [NSRegularExpression regularExpressionWithPattern:@"(([\\d\\.\\+-]+\\s?){0,3})" options:0 error:&_error];
if (!_error) {
    [_regExp enumerateMatchesInString:_string options:NSMatchingReportProgress range:NSMakeRange(0, _string.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
        FloatNumbers _floatNumbers = FloatNumbersMake(MAXFLOAT, MAXFLOAT, MAXFLOAT);
        @try {
            NSArray *_groupOfNumbers = [[_string substringWithRange:result.range] componentsSeparatedByString:@" "];
            _floatNumbers.a = [[_groupOfNumbers objectAtIndex:0] doubleValue];
            _floatNumbers.b = [[_groupOfNumbers objectAtIndex:1] doubleValue];
            _floatNumbers.c = [[_groupOfNumbers objectAtIndex:2] doubleValue];
        }
        @catch (NSException *exception) {
        }
        @finally {
            if ([_lock tryLock]) [_mutableArray addObject:NSStringFromFloatNumbers(_floatNumbers)], [_lock unlock];
            *stop = (flags == NSMatchingHitEnd);
        }
    }];
} else {
    NSLog(@"%@", _error);
}

_mutableArray有数字,每个对象是一组3;下面是一个如何从数组中读回所需的3个数字组的示例,您可以使用之后的值。

// reading the numbers back
FloatNumbers _secondGroupOf3Numbers = FloatNumbersFromString([_mutableArray objectAtIndex:1]);

NSLog(@"a : %f, b : %f, c : %f", _secondGroupOf3Numbers.a, _secondGroupOf3Numbers.b, _secondGroupOf3Numbers.c);

因此,它会记录第二组3个数字,如:

a : 0.015760, b : 0.020224, c : 0.027297

(请记住:这些只是调试控制台的舍入值,浮点数与它们被解析的相同。)

答案 2 :(得分:0)

如果我理解正确,你想收到一个字符串数组,每个字符串必须包含3个数字? 让我们使用regexp:

NSString *inputString = @"0.015637 0.0205293 0.0270841 0.0157598 0.0202236 0.0272967 0.013217 0.0205293 0.0283439 0.0115028 0.0205293 0.0290539 0.0107803 0.0202236 0.0296187 -0.029892 0.0194995 0.0108798 -0.0299242 0.0191089 0.0108915 0.0243682 0.0194995 0.0204474 0.0307989 0.0205293 -0.00543068 0.0313996 0.0202236 0.00274711 -0.0157598 0.0202236 0.0272967 -0.0180789 0.0202236 0.0258193 -0.0182457 0.0194995 -0.0260576 -0.0182654 0.0191089 -0.0260857 -0.0134582 0.0191089 0.0191089";

NSError *error;
// Creating regexp that will split input string to substring with 3 numbers
NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:@"(([\\d\\.-]+\\s?){3})"
                                                                        options:0
                                                                          error:&error];

// TODO: Handle error if appear

//
NSArray *matches = [regExp matchesInString:inputString
                                   options:0
                                     range:NSMakeRange(0, [inputString length])];

NSMutableArray *result = [NSMutableArray new];

for (NSTextCheckingResult *match in matches) {
    // Get the matching string
    NSString *substring = [inputString substringWithRange:[match range]];
    // Trim whitespace at the end
    substring = [substring stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    [result addObject:substring];
}