【问题标题】:Sort array in ascending order and remove duplicate values in objective- c按升序对数组进行排序并删除objective-c中的重复值
【发布时间】:2015-06-18 08:23:04
【问题描述】:

我有一个水平和垂直可滚动的表格。我从 Web 服务(json)中获取标题和第一列的数据。我想按升序对数据进行排序,并从标题和第一列中删除重复数据。为了删除重复值,我使用了以下代码:

-(void) requestFinished: (ASIHTTPRequest *) request
{
    NSString *theJSON = [request responseString];

    SBJsonParser *parser = [[SBJsonParser alloc] init];

    NSMutableArray *jsonDictionary = [parser objectWithString:theJSON error:nil];

    headData = [[NSMutableArray alloc] init];
    NSMutableArray *head = [[NSMutableArray alloc] init];

    leftTableData = [[NSMutableArray alloc] init];
    NSMutableArray *left = [[NSMutableArray alloc] init];

    rightTableData = [[NSMutableArray alloc]init];

    for (NSMutableArray *dictionary in jsonDictionary)
    {
        Model *model = [[Model alloc]init];

        model.cid = [[dictionary valueForKey:@"cid"]intValue];
        model.iid = [[dictionary valueForKey:@"iid"]intValue];
        model.yr = [[dictionary valueForKey:@"yr"]intValue];
        model.val = [dictionary valueForKey:@"val"];

        [mainTableData addObject:model];

        [head addObject:[NSString stringWithFormat:@"%ld", model.yr]];
        [left addObject:[NSString stringWithFormat:@"%ld", model.iid]];
    }
    NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:head];
    headData = [[orderedSet array] mutableCopy];

//    NSSet *set = [NSSet setWithArray:left];
//    NSArray *array2 = [set allObjects];
//    NSLog(@"%@", array2);

    NSOrderedSet *orderedSet1 = [NSOrderedSet orderedSetWithArray:left];
    NSMutableArray *arrLeft = [[orderedSet1 array] mutableCopy];

    //remove duplicate enteries from header array
    [leftTableData addObject:arrLeft];


    NSMutableArray *right = [[NSMutableArray alloc]init];
    for (int i = 0; i < arrLeft.count; i++)
    {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        for (int j = 0; j < headData.count; j++)
        {
            /* NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.iid == %ld", [[arrLeft objectAtIndex:i] intValue]];
             NSArray *filteredArray = [mainTableData filteredArrayUsingPredicate:predicate];*/
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.iid == %ld AND SELF.yr == %ld", [[arrLeft objectAtIndex:i] intValue], [[headData objectAtIndex:j] intValue]];
            NSArray *filteredArray = [mainTableData filteredArrayUsingPredicate:predicate];

            if([filteredArray count]>0)
            {
                Model *model = [filteredArray objectAtIndex:0];
                [array addObject:model.val];
            }
        }
        [right addObject:array];
    }
    [rightTableData addObject:right];
}

如何按升序对数组进行排序?

请帮忙。

【问题讨论】:

  • 希望此链接对您有所帮助。 [链接]stackoverflow.com/questions/1025674/…
  • 我已经删除了重复值。我想按升序设置数据。
  • 对于您所说的所有答案,您都收到了有关 iid 的错误。这是你的问题。这不是答案有问题,这是您的代码和模型有问题。所有这些答案都有效。您提供的有关数据的信息非常少,因此无法了解为什么会发生这种情况。你能包括你的模型代码和显示他错误的排序代码吗?
  • 另外,您不需要使用 SBJSONParser。只需使用 NSJSONSerialization。

标签: ios objective-c json sorting nsmutablearray


【解决方案1】:

好的,所以你有一个看起来像这样的模型对象......

@interface Model: NSObject

@property NSNumber *idNumber;
@property NSNumber *year;
@property NSString *value;

@end

注意,我故意使用NSNumber 而不是NSInteger,原因将变得很清楚。

目前,您正试图在一个地方做很多事情。不要这样做。

创建一个新对象来存储这些数据。然后,您可以添加方法来获取所需的数据。看到您在按年份划分的表格视图中显示,然后每个部分按 idNumber 排序,那么我会做这样的事情......

@interface ObjectStore: NSObject

- (void)addModelObject:(Model *)model;

// standard table information
- (NSInteger)numberOfYears;
- (NSInteger)numberOfIdsForSection:(NSinteger)section;

// convenience methods
- (NSNumber *)yearForSection:(NSInteger)section;
- (NSNumber *)idNumberForSection:(NSInteger)section row:(NSInteger)row;
- (NSArray *)modelsForSection:(NSInteger)section row:(NSInteger)row;

// now you need a way to add objects
- (void)addModelObject:(Model *)model;

@end

现在来实现它。

我们要将所有内容存储在一本字典中。键是years,对象是字典。在这些字典中,键是idNumbers,对象是数组。这些数组将保存模型。

就这样……

{
    2010 : {
        1 : [a, b, c],
        3 : [c, d, e]
    },
    2013 : {
        1 : [g, h, u],
        2 : [e, j, s]
    }
}

我们也将使用所有方便的方法来做到这一点。

@interface ObjectStore: NSObject

@property NSMutableDictionary *objectDictionary;

@end

@implementation ObjectStore

 + (instancetype)init
{
    self = [super init];

    if (self) {
        self.objectDictionary = [NSMutableDictionary dictionary];
    }

    return self;
}

 + (NSInteger)numberOfYears
{
    return self.objectDictionary.count;
}

 + (NSInteger)numberOfIdsForSection:(NSinteger)section
{
    // we need to get the year for this section in order of the years.
    // lets create a method to do that for us.
    NSNumber *year = [self yearForSection:section];

    NSDictionary *idsForYear = self.objectDictionary[year];

    return idsForYear.count;
}

- (NSNumber *)yearForSection:(NSInteger)section
{
    // get all the years and sort them in order
    NSArray *years = [[self.obejctDictionary allKeys] sortedArrayUsingSelector:@selector(compare:)];

    // return the correct year
    return years[section];
}

- (NSNumber *)idNumberForSection:(NSInteger)section row:(NSInteger)row
{
    // same as the year function but for id
    NSNumber *year = [self yearForSection:section];

    NSArray *idNumbers = [[self.objectDictionary allKeys]sortedArrayUsingSelector:@selector(compare:)];

    return idNumbers[row];
}

- (NSArray *)modelsForSection:(NSInteger)section row:(NSInteger)row
{
    NSNumber *year = [self yearForSection:section];
    NSNumber *idNumber = [self idForSection:section row:row];

    return self.objectDictionary[year][idNumber];
}

// now we need a way to add objects that will put them into the correct place.

- (void)addModelObject:(Model *)model
{
    NSNumber *modelYear = model.year;
    NSNumber *modelId = model.idNumber;

    // get the correct storage location out of the object dictionary
    NSMutableDictionary *idDictionary = [self.objectDictionary[modelYear] mutableCopy];

    // there is a better way to do this but can't think atm
    if (!idDictionary) {
        idDictionary = [NSMutableDictionary dictionary];
    }

    NSMutableArray *modelArray = [idDictionary[modelId] mutableCopy];

    if (!modelArray) {
        modelArray = [NSMutableArray array];
    }

    // insert the model in the correct place.
    [modelArray addObject:model];
    idDictionary[modelId] = modelArray;
    self.objectDictionary[modelYear] = idDictionary;
}

@end

通过所有这些设置,您现在可以用这个替换您的复杂函数...

-(void) requestFinished: (ASIHTTPRequest *) request
{
    NSString *theJSON = [request responseString];
    SBJsonParser *parser = [[SBJsonParser alloc] init];
    NSDictionary *jsonDictionary = [parser objectWithString:theJSON error:nil];

    for (NSDictionary *dictionary in jsonDictionary)
    {
        Model *model = [[Model alloc]init];

        model.cid = [dictionary valueForKey:@"cid"];
        model.idNumber = [dictionary valueForKey:@"iid"];
        model.year = [dictionary valueForKey:@"yr"];
        model.val = [dictionary valueForKey:@"val"];

        [self.objectStore addModelObject:model];
    }
}

要获取特定行的模型,只需使用...

[self.objectStore modelsForSection:indexPath.section row:indexPath.row];

获取tableview委托方法中的section数量...

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [self.objectStore numberOfYears];
}

不要在视图控制器中弄乱模型。

欢迎使用 MVC 模式。

这里有一大堆代码,但通过将所有代码放在这里,您可以从 VC 中删除所有复杂代码。

【讨论】:

    【解决方案2】:

    NSSet 仅在其内部保留非重复对象,因此要在数组中仅保留唯一对象,您可以使用 NSSet 作为 -

    假设你有一个包含重复对象的数组

    NSArray *arrayA = @[@"a", @"b", @"a", @"c", @"a"];
    NSLog(@"arrayA is: %@", arrayA);
    
    //create a set with the objects from above array as
    //the set will not contain the duplicate objects from above array
    NSSet *set = [NSSet setWithArray: arrayA];
    
    // create another array from the objects of the set
    NSArray *arrayB = [set allObjects];
    NSLog(@"arrayB is: %@", set);
    

    上面的输出看起来像:

    arrayA is: (
        a,
        b,
        a,
        c,
        a
    )
    arrayB is: {(
        b,
        c,
        a
    )}
    

    要按升序对可变数组进行排序,您可以使用NSSortDescriptorsortUsingDescriptors:sortDescriptors。您还需要根据将排序的数组提供键。

    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"key" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    [array sortUsingDescriptors:sortDescriptors];
    [sortDescriptor release];
    

    【讨论】:

    • 我试过了。由于未捕获的异常'NSUnknownKeyException',我给出了错误终止应用程序,原因:'[<__nscfstring> valueForUndefinedKey:]:此类不符合键 iid 的键值编码。'
    • 你能提供错误信息吗,还有你在sortDEscriptor中指定了key吗?
    • 我已将模型定义为接口模型:NSObject 属性(分配,非原子)NSInteger cid;属性(分配,非原子)NSInteger iid;属性(分配,非原子)NSInteger yr;属性(强,非原子) NSString *val;
    • 我必须对 iid 和 yr 进行排序
    • NSSortDescriptor *iidDescriptor = [[NSSortDescriptor alloc] initWithKey:@"iid" 升序:YES]; NSSortDescriptor *yrDescriptor = [[NSSortDescriptor alloc] initWithKey:@"yr" 升序:YES]; NSArray *sortDescriptors = @[iidDescriptor, yrDescriptor]; NSArray *sortedArray = [数组 sortedArrayUsingDescriptors:sortDescriptors];
    【解决方案3】:

    在这里你会得到你想要的。

    //sort description will used to sort array.
    NSSortDescriptor *descriptor=[[NSSortDescriptor alloc] initWithKey:@"iid" ascending:YES];
    NSArray *descriptors=[NSArray arrayWithObject: descriptor];
    NSArray *reverseOrder=[arrLeft sortedArrayUsingDescriptors:descriptors];
    

    reverseOrder 是你想要的输出。

    还有另一种方法可以对遵循模型的对象进行排序。

    NSArray *someArray = /* however you get an array */    
    NSArray *sortedArray = [someArray sortedArrayUsingComparator:^(id obj1, id obj2) {
     NSNumber *rank1 = [obj1 valueForKeyPath:@"iid"];
    NSNumber *rank2 = [obj2 valueForKeyPath:@"iid"];
    return (NSComparisonResult)[rank1 compare:rank2];
    }];
    

    这里sortedArray 是我们的输出。

    您也可以为 yr 键替换相同的内容。

    【讨论】:

    • 出现错误,此类与键 iid 的键值编码不兼容。'
    • @Itaws,您是否遇到编译器错误或崩溃?实际上这段代码在这里工作,所以我认为你身边还有一些小的变化。你能给我你的arrLeft吗?
    • 可能是您的错误,原因如下。stackoverflow.com/questions/3088059/…
    【解决方案4】:

    这就是我按升序对标题数据进行排序并从标题和最左侧列中删除重复项所做的操作。希望这对其他人有帮助

    NSOrderedSet *orderedSet3 = [NSOrderedSet orderedSetWithArray:head3];
    headData3 = [[orderedSet3 array] mutableCopy];
    [headData3 sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2)
    {
        return [str1 compare:str2 options:(NSNumericSearch)];
    }];
    
    NSOrderedSet *orderedSet4 = [NSOrderedSet orderedSetWithArray:left3];
    NSMutableArray *arrLeft3 = [[orderedSet4 array] mutableCopy];
    
    [leftTableData3 addObject:arrLeft3];
    

    【讨论】:

      猜你喜欢
      • 2013-02-03
      • 2018-10-02
      • 2021-11-20
      • 2021-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      相关资源
      最近更新 更多