2012-10-30 73 views
2

我有一个NSArray包含几个NSDictionary实例。除其他字段外,每个NSDictionary都有一个名为rating的对象和一个numberOfVotes(均为int)。如何对数组进行排序,以便按rating/numberOfVotes排序?更一般地说,我可以通过执行上述操作来对其进行分类吗?或者,将每个操作的值添加到每个NSDictionary的另一个对象然后按此排序?NSArray按功能排序

谢谢

编辑 - 我已添加以下内容。仍然没有正确排序。一个问题:这个数组是否应该适用于2个以上的对象。 (对象数量会有所不同)

[sortedArray sortedArrayUsingComparator:^NSComparisonResult(id dict1, id dict2) 
{ 
    MyObj *obj1 = (MyObj *)dict1; 
    MyObj *obj2 = (MyObj *)dict2; 

    int rating1 = obj1.rating.intValue; 
    int rating2 = obj2.rating.intValue; 

    int number1 = obj1.number_of_votes.intValue; 
    int number2 = obj2.number_of_votes.intValue; 

    double key1 = ((double)rating1)/number1; 
    double key2 = ((double)rating2)/number2; 

    if (key1 < key2) 
    { 
     return NSOrderedDescending; 
    } 

    if (key2 < key1) 
    { 
     return NSOrderedAscending; 
    } 
    return NSOrderedSame; 

}]; 

回答

4

您可以定义一个自定义比较器来使用您正在寻找的那种复合排序键。如果在字典中没有充分的理由拥有该排序键,除了执行排序之外,不要将词项添加到字典中。

array = [array sortedArrayUsingComparator: ^(id obj1, id obj2) { 
    int rating1 = [[obj1 objectForKey:@"rating"] intValue]; 
    int numberOfVotes1 = [[obj1 objectForKey:@"numberOfVotes"] intValue]; 
    int rating2 = [[obj2 objectForKey:@"rating"] intValue]; 
    int numberOfVotes2 = [[obj2 objectForKey:@"numberOfVotes"] intValue]; 
    double key1 = ((double)rating1)/numberOfVotes1; 
    double key2 = ((double)rating2)/numberOfVotes2; 
    if (key1 > key2) { 
     return (NSComparisonResult)NSOrderedDescending; 
    } 

    if (key1 < key2) { 
     return (NSComparisonResult)NSOrderedAscending; 
    } 
    return (NSComparisonResult)NSOrderedSame; 
}]; 

注:sortedArrayUsingComparator:方法不代替数组进行排序;相反,它返回一个排序的副本。如果您想要就地分拣,请使用NSMutableArray

+0

请参阅我的更新回答 –

+0

@AndreiFilip是的,这将适用于必要的项目。但是,这不会*排列阵列;它会返回数组的一个有序副本。 – dasblinkenlight

+0

它令人敬畏的cos它使用块,ftw! ;-) –

0

您寻求的方法家族的前缀为sortedArray

对于函数(这是多个选项之一),请参阅:-[NSArray sortedArrayUsingFunction:context:]

0

编辑:如果你想要做ratingnumberOfVotes分,你将有一个功能或比较块进行排序或更换字典,其中有计算rating/numberOfVotes的方法的模型对象。使用NSSortDescriptor

NSArray *sorted = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects: 
    [NSSortDescriptor sortDescriptorWithKey:@"rating" ascending:YES], 
    [NSSortDescriptor sortDescriptorWithKey:@"numberOfVotes" ascending:YES], 
    nil] 
]; 
+0

它看起来像OP希望通过'numberOfVotes'划分'rating',而不是通过'numberOfVotes'来解决冲突。 – dasblinkenlight

+0

啊。然后,OP将不得不使用比较器/函数(请参阅@dasblinkenlight)或从字典中转到模型对象,并定义计算适当值以排序的方法。 – Jesper

1

的适当的方式将使用块这样

NSArray *sortedArray; 

sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { 
    float first = [[(NSDictionary*)a objectForKey:@"rating"] floatValue]/ 
         [[(NSDictionary*)a objectForKey:@"numberOfVotes"] floatValue]; 
    float second = [[(NSDictionary*)a objectForKey:@"rating"] floatValue]/ 
         [[(NSDictionary*)a objectForKey:@"numberOfVotes"] floatValue]; 
return [[NSNumber numberWithFloat:first] compare: [NSNumber numberWithFloat:second]]; 
}]; 

您可能会发现更多的方法来比较:

How to sort an NSMutableArray with custom objects in it?

0

过滤数据是在计算基本任务之一。

您可以通过多种方式进行排序。

  1. NSPredicate

    你可以看到的例子here

  2. NSSortDescriptor

    你可以看到的例子here

  3. 正则表达式

  4. Set操作

  5. 键 - 值编码

0

理想情况下,你应该通过自定义对象替换NSDictionary,与像ratingnumberOfVotes性能。然后,您可以在此自定义对象上声明方法compare:,并将其用作选择器对数组进行排序。

您可以使用块代码对对象进行排序,但将实现抽象为自定义对象会更清晰。

0

你可以在这里使用NSSortDescriptor进行排序,例如你的数组包含几个NSDictionnaries,名字是dataArray。

NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:rating 
          ascending:YES]; 
NSArray * keyArrray = [NSArray arrayWithObjects:descriptor, nil]; 
NSArray * sortedArray = [dataArray sortedArrayUsingDescriptors:keyArrray]; 

在NSSortDescriptor的帮助下,我们可以对任何数据类型键值对进行排序。