9

这是一个开放的问题,而不是与错误相关的问题,所以如果你不喜欢回答这类问题,请不要发火。

我在 .csv 文件中有一个巨大的(!)船舶列表,由,

矩阵是这样组织的: 在此处输入图像描述
用不同的数据重复大约 500 次。

现在,我希望将其读入对象,可进一步用于填充UITableView 当前,我将数据硬编码到对象文件中,如下所示

arrayWithObjectsForTableView = [[NSMutableArray alloc] init];
if ([boatsFromOwner isEqualToString:@"Owner1"]) {
    cargoShips* ship = [[cargoShips alloc]init];
    ship.name = @"name1";
    ship.size = 1000;
    ship.owner = @"Owner1";

    [self.boatsForOwner addObject:ship];

    ship = [[cargoShips alloc]init];
    ship.name = @"Name 2";
    ship.size = 2000;
    ship.owner = @"Owner2";

依此类推,使用 if-else。这是一个不好的方法,因为 1)它很无聊并且需要很长时间 2)如果我想更新信息需要更多时间。所以,我认为以编程方式从矩阵中读取而不是自己做会更聪明。是的,船长显然是来探望我的大脑的。

那么,问题来了! 我怎样才能读取看起来像这样的 .csv 文件: 以对象的形式将在此处输入图像描述 所有者的船添加到 aNSMutableArray中。(所以它们可以用来喂我UITableView的船。

我还希望可以选择按不同的内容进行排序,例如建造国家、运营商等。如何制作将从 .csv 读取的相关船只提供给对象的代码?我不太了解编程,因此非常感谢您提供深入的答案。

4

3 回答 3

11

您的处理深度将决定此任务需要哪种数据结构。这是我会使用的方法:

1:将文件读.csv入一个巨大的NSString对象:

NSString *file = [[NSString alloc] initWithContentsOfFile:yourCSVHere];

2:获取各行:

NSArray *allLines = [file componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

3:对于每一行,获取各个组件:

for (NSString* line in allLines) {
    NSArray *elements = [line componentsSeparatedByString:@","];
    // Elements now contains all the data from 1 csv line
    // Use data from line (see step 4)
}

4:这取决于你。我的第一个想法是创建一个类来存储您的所有数据。例如:

@interface Record : NSObject
//...
@property (nonatomic, copy) NSString *name
@property (nonatomic, copy) NSString *owner
// ... etc
@end

4a:然后,回到第 3 步,为每一行创建一个Record对象,然后将所有 Record 对象放入一个单独的NSArray(范围更大的东西!)。

5:使用NSArray包含所有Record对象的你作为你的数据源UITableView

步骤 4 和 5 的实施取决于您。.csv对于中等大小的文件,这可能就是我会这样做的方式。

编辑:这是生成Records.

//
NSMutableArray *someArrayWithLargerScope = [[NSMutableArray alloc] init];
//

NSString *file = [[NSString alloc] initWithContentsOfFile:yourCSVHere];
NSArray *allLines = [file componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet];

for (NSString* line in allLines) {
    NSArray *elements = [line componentsSeparatedByString@","];
    Record *rec = [[Record alloc] init];
    rec.name = [elements objectAtIndex:0];
    rec.owner = [elements objectAtIndex:1];
    // And so on for each value in the line.
    // Note your indexes (0, 1, ...) will be determined by the
    // order of the values in the .csv file.
    // ...
    // You'll need one `Record` property for each value.

    // Store the result somewhere
    [someArrayWithLargerScope addObject:rec];
}
于 2013-01-25T01:48:18.280 回答
3

就 CSV 解析而言,假设您可以花费内存,这可能是最容易将整个内容读取到 a 的NSString,将其拆分为换行符,然后将每一行拆分为逗号,基本上正如 PLPiper 所建议的那样。

那时我会绕道进入键值编码。为 CSV 文件中的列提供与运行时对象上的属性完全相同的名称。然后你可以写如下内容:

// this method will create an object of the given type then push the values
// from valueRow to the properties named by headingRow. So, ordinarily,
// headingRow will be the first row in your CSV, valueRow will be any other
- (id)populatedObjectOfType:(Class)type withHeadingRow:(NSArray *)headingRow valueRow:(NSArray *)valueRow
{
    // we need the count of fields named in the heading row to 
    // match the count of fields given in this value row
    if([headingRow count] != [valueRow count]) return nil;

    // autorelease if you're not using ARC
    id <NSObject> newInstance = [[type alloc] init];

    // we need to enumerate two things simultaneously, so
    // we can fast enumerate one but not the other. We'll
    // use good old NSEnumerator for the other
    NSEnumerator *valueEnumerator = [valueRow objectEnumerator];
    for(NSString *propertyName in headingRow)
    {
        [newInstance setValue:[valueEnumerator nextObject] forKey:propertyName];
    }

    return newInstance;
}

... elsewhere ....
CargoShip *newShip = [self populateObjectOfType:[CargoShip class] withHeadingRow:[csvFile objectAtIndex:0] valueFor:[csvFile objectAtIndex:1]];

主要需要注意的是,内置机制将在标量和对象之间转换,但不会在不同类型的对象之间转换。因此,如果你有 allNSString和 C 整数类型(shortintNSUInteger等),你会很好,但如果你有一些NSStrings ,比如说,一些NSNumbers ,那么你最终会得到存储在数字槽中的字符串。看起来您正在使用 C 整数类型(这很正常),所以您应该没问题。

在过滤方面,您可以使用NSPredicates. 例如,假设您有一个CargoShips 数组,并且希望每个数组的 asize至少为 500:

NSArray *bigShips = [allShips filteredArrayUsingPredicate:
    [NSPredicate predicateWithFormat:@"size > 500"]];

同样,对于排序,您可以在问题上抛出一些NSSortDescriptors。例如

NSArray *shipsSortedBySize = [allShips sortedArrayUsingDescriptors:
     @[[NSSortDescriptor sortDescriptorWithKey:@"size" ascending:YES]]];
于 2013-01-25T02:18:45.027 回答
3

你可以使用这个链接,
https://github.com/davedelong/CHCSVParser
是.csv 解析器,CHCSVParser 可以配置解析其他“字符分隔”文件格式,例如“TSV”(制表符分隔)或逗号分隔。

于 2013-01-25T06:28:53.420 回答