【问题标题】:Trying to create an array of dictionaries, keep getting the same dictionary repeated in the array尝试创建一个字典数组,不断在数组中重复相同的字典
【发布时间】:2014-03-19 02:28:49
【问题描述】:

我正在尝试使用 NSData 从文本文件中提取信息,然后将其加载到字典中。

首先我创建一个文本文件的字符串,并将每条记录加载到一个数组中。

然后我将每条记录分解为单独的数据元素。

我遇到的问题是,当字典完全填充后,我使用 addObject 将其加载到数组中,它确实成功了。问题是,当下一个循环创建一个新字典时,同一个字典被加载到数组中,我最终得到一个包含所有相同字典的数组,而不是多个不同的字典对象。

我猜我犯了一些简单的错误导致了这个错误。任何帮助将不胜感激。

NSString *clientListFile = [NSURL URLWithString:@"/textfile"];

NSData *clientListDataFile = [NSData dataWithContentsOfFile:clientListFile];

NSString *clientListString = [[NSString alloc]initWithBytes:[clientListDataFile bytes] length:[clientListDataFile length] encoding:NSUTF8StringEncoding];

NSString *returnDelimiter = @"\n";
NSString *commaDelimiter = @",";
NSString *exclamationDelimiter = @"!";

NSArray *keysAndObjects = [[NSArray alloc]init];
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
NSMutableArray *clientListOfDictionaries = [[NSMutableArray alloc]init];

NSArray *sentenceArray = [clientListString componentsSeparatedByString:returnDelimiter];
    for (int i = 0; i < [sentenceArray count]; i=i+1) {
        [clientList removeAllObjects]; //to start with a fresh dictionary for the next iteration
        NSString *recordSentence = [sentenceArray objectAtIndex:i];

        NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];

        for (int j = 0; j < [attributes count]; j = j+1) {
            NSString *pairsOfItems = [attributes objectAtIndex:j];

            //a small arry, of only two objects, the first is the key, the second is the object
            keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];


            [clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];


            }
        [clientListOfDictionaries addObject:clientList];

        }

当我使用 NSLog 查看字典中的内容时,我重复了同一个字典的多个对象,即使在迭代的早期,我也可以看到代码正在创建单独且唯一的字典。

【问题讨论】:

    标签: ios objective-c arrays dictionary


    【解决方案1】:

    代替这一行

    [clientListOfDictionaries addObject:clientList];
    

    你可以拥有

    [clientListOfDictionaries addObject:[[NSArray alloc] initWithArray:clientList];
    

    这样您将向 clientListOfDictionaries 添加新数组,而不是同一个。

    【讨论】:

      【解决方案2】:

      移动这一行:

      NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
      

      到第一个 for 循环行之后,然后删除该行:

      [clientList removeAllObjects];
      

      为每次迭代创建一个新字典很重要。

      您还应该删除以下行:

      NSArray *keysAndObjects = [[NSArray alloc]init];
      

      并改变:

      keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
      

      到:

      NSArray *keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
      

      【讨论】:

        【解决方案3】:

        您在 for 循环之外分配并初始化了您的 clientList 字典,因此您只有一个字典,您将多次将其存储在数组中。将字典添加到数组中不会复制它,它只是添加一个指向对象的指针。

        你需要移动

        NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
        

        在你的第一个 for 循环中代替

        [clientList removeAllObjects];
        

        另外,componentsSeparatedByString: 返回一个 NSArray,所以你不需要分配和初始化一个。您可以简单地定义变量 -

        NSArray *keysAndObjects;
        

        【讨论】:

          【解决方案4】:

          因为您对循环的每次迭代都使用相同的 clientList 变量。您每次都需要创建一个全新的字典对象。

          试试这个修改后的代码:

          NSData *clientListDataFile = [NSData dataWithContentsOfFile:clientListFile];
          NSString *clientListString = [[NSString alloc]initWithBytes:[clientListDataFile bytes] length:[clientListDataFile length] encoding:NSUTF8StringEncoding];
          
          NSString *returnDelimiter = @"\n";
          NSString *commaDelimiter = @",";
          NSString *exclamationDelimiter = @"!";
          
          NSArray *keysAndObjects = nil;
          NSMutableArray *clientListOfDictionaries = [[NSMutableArray alloc] init];
          
          NSArray *sentenceArray = [clientListString componentsSeparatedByString:returnDelimiter];
          
          for (NSUInteger i = 0; i < [sentenceArray count]; ++i) {
              NSMutableDictionary *clientList = [[NSMutableDictionary alloc] init]; //to start with a fresh dictionary for the next iteration
              NSString *recordSentence = [sentenceArray objectAtIndex:i];
          
              NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
          
              for (NSUInteger j = 0; j < [attributes count]; ++j) {
                  NSString *pairsOfItems = [attributes objectAtIndex:j];
          
                  //a small arry, of only two objects, the first is the key, the second is the object
                  keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
          
                  [clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
              }
          
              [clientListOfDictionaries addObject:clientList];
          }
          

          另一种选择,虽然可能效率较低,是换行:

          [clientListOfDictionaries addObject:clientList];
          

          [clientListOfDictionaries addObject:[clientList copy]];
          

          这使您可以继续使用相同的clientList 变量,因为您将它的副本添加到clientListOfDictionaries 数组中。我只是指出这一点,因为它可能会帮助您了解正在发生的事情。

          另外,请注意我为您更改了这一行:

          NSArray *keysAndObjects = [[NSArray alloc]init];
          

          NSArray *keysAndObjects = nil;
          

          因为它只是一个由您调用componentsSeparatedByString 设置的指针,所以您不需要为它分配一个数组。该数组将在您的第一次循环迭代中消失。

          【讨论】:

            【解决方案5】:

            应该将新字典添加到数组中。否则它不会添加到数组中。数组中的每个对象都有相同的字典映射。所以它会给你相同的字典值。为每个对象创建新字典并添加到数组中。

            for (int i = 0; i < [sentenceArray count]; i=i+1) {
            
                NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
            
                NSString *recordSentence = [sentenceArray objectAtIndex:i];
            
                NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
            
                for (int j = 0; j < [attributes count]; j = j+1) {
            
                    NSString *pairsOfItems = [attributes objectAtIndex:j];
            
                    //a small arry, of only two objects, the first is the key, the second is the object
                    NSArray *keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
            
                    [clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
            
                    }
            
                [clientListOfDictionaries addObject:clientList];
            
                }
            

            【讨论】:

            • 您真的觉得有必要重复之前的其他 4 个答案吗?
            猜你喜欢
            • 2022-09-28
            • 2018-01-30
            • 2023-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多