如何对带有自定义对象的NSMutableArray进行排序?

2020/10/26 13:43 · ios ·  · 0评论

我想做的事情看起来很简单,但是我在网上找不到任何答案。我有一个NSMutableArray对象,可以说它们是“人”的对象。我想NSMutableArray按Person.birthDate对其进行排序NSDate

我认为这与这种方法有关:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

在Java中,我可以使我的对象实现Comparable,或者将Collections.sort与内联自定义比较器一起使用...实际上,您如何在Objective-C中做到这一点?

比较方法

您可以为对象实现比较方法:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor(更好)

甚至通常更好:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

您可以通过在数组中添加多个键来轻松地对多个键进行排序。也可以使用自定义的比较器方法。看一下文档

块(发光!)

从Mac OS X 10.6和iOS 4开始,也有可能使用块进行排序:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

性能

The -compare: and block-based methods will be quite a bit faster, in general, than using NSSortDescriptor as the latter relies on KVC. The primary advantage of the NSSortDescriptor method is that it provides a way to define your sort order using data, rather than code, which makes it easy to e.g. set things up so users can sort an NSTableView by clicking on the header row.

NSMutableArray方法sortUsingFunction:context:

您将需要设置一个比较函数,该函数接受两个对象(类型为Person,因为您正在比较两个Person对象)和一个上下文参数。

这两个对象只是的实例Person第三个对象是字符串,例如@“ birthDate”。

此函数返回一个NSComparisonResultNSOrderedAscending如果PersonA.birthDate< ,则返回PersonB.birthDateNSOrderedDescending如果PersonA.birthDate> ,它将返回PersonB.birthDate最后,NSOrderedSame如果PersonA.birthDate== ,它将返回PersonB.birthDate

这是粗糙的伪代码;您将需要充实一个日期与另一个日期的“较少”,“更多”或“相等”的含义(例如比较秒-自纪元等):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

如果您想要更紧凑的东西,可以使用三元运算符:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

如果您经常这样做,内联可能会加快速度。

我在iOS 4中使用块进行了此操作。必须将数组的元素从id转换为我的类类型。在这种情况下,这是一个名为Score的类,其属性为points。

Also you need to decide what to do if the elements of your array are not the right type, for this example I just returned NSOrderedSame, however in my code I though an exception.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS: This is sorting in descending order.

从iOS 4开始,您还可以使用块进行排序。

对于此特定示例,我假设您数组中的对象具有“ position”方法,该方法返回NSInteger

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

注意:“排序的”数组将自动发布。

我尝试了所有,但这对我有用。在一个类中,我有另一个名为“ crimeScene”的,并希望按“ crimeScene的属性进行排序

这就像一个魅力:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

GeorgSchölly的第二个答案中缺少一个步骤,但随后效果很好。

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

//添加了's',因为我在复制粘贴时浪费了时间,并且在sortedArrayUsingDescriptors中没有's'时失败了

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

谢谢,一切正常...

您的Person对象需要实现一个方法,例如compare:该方法接受另一个Person对象,然后NSComparisonResult根据这两个对象之间的关系返回

然后,您将致电给sortedArrayUsingSelector:@selector(compare:)并且应该完成。

还有其他方法,但据我所知,该Comparable接口还没有可可的设备。使用sortedArrayUsingSelector:可能是最轻松的方法。

iOS 4块将为您节省:)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html有点描述

对于NSMutableArray,请使用sortUsingSelector方法。它对它进行排序,而不创建新实例。

您可以根据需要使用以下通用方法。它应该可以解决您的问题。

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];

如果您只排序的数组NSNumbers,则可以通过1次调用对其进行排序:

[arrayToSort sortUsingSelector: @selector(compare:)];

之所以可行,是因为数组中的对象(NSNumber对象)实现了compare方法。您可以对NSString对象甚至对实现比较方法的自定义数据对象数组执行相同的操作。

这是一些使用比较器块的示例代码。它对字典数组进行排序,其中每个字典在键“ sort_key”中都包含一个数字。

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

上面的代码完成了为每个排序键获取一个整数值并将其进行比较的工作,以说明如何执行此操作。由于NSNumber对象实现了compare方法,因此可以更简单地重写它:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

或者比较器的主体甚至可以蒸馏成1行:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

我倾向于使用简单的语句和大量的临时变量,因为代码更易于阅读和调试。编译器还是会优化掉临时变量,因此多行合一版本没有任何优势。

-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}

我创建了一个小的类别方法库,称为Linq to ObjectiveC,它使这种事情变得更加容易。结合使用带有键选择器sort方法,可以按birthDate以下方式进行排序

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]

我只是根据自定义要求进行了多级排序。

//对值进行排序

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

在某些项目中使用了sortUsingFunction :::

int SortPlays(id a, id b, void* context)
{
    Play* p1 = a;
    Play* p2 = b;
    if (p1.score<p2.score) 
        return NSOrderedDescending;
    else if (p1.score>p2.score) 
        return NSOrderedAscending;
    return NSOrderedSame;
}

...
[validPlays sortUsingFunction:SortPlays context:nil];

您可以使用NSSortDescriptor对带有自定义对象的NSMutableArray进行排序

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

排序NSMutableArray非常简单:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];

使用NSComparator排序

如果要对自定义对象进行排序,则需要提供NSComparator,用于比较自定义对象。该块返回一个NSComparisonResult值,以表示两个对象的顺序。因此为了排序整个数组NSComparator,按以下方式使用。

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

使用NSSortDescriptor进行排序

例如,假设我们有一个包含自定义类实例的数组,那么Employee的属性为firstname,lastname和age。
以下示例说明了如何创建NSSortDescriptor,该NSSortDescriptor可用于按年龄键对数组内容进行升序排序。

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

使用自定义比较进行排序

名称是字符串,并且在对要呈现给用户的字符串进行排序时,应始终使用本地化的比较。
通常,您还希望执行不区分大小写的比较。这是一个带有(localizedStandardCompare :)的示例,用于按姓和名对数组进行排序。

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

有关参考和详细讨论,请参阅:https :
//developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html

http://www.ios-blog.co.uk/tutorials / objective-c /如何使用自定义对象对nsarray进行排序/

Swift的协议和函数式编程非常容易,您只需使您的类符合Comparable协议,实现该协议所需的方法,然后使用sorted(by:)高阶函数即可创建一个排序数组,而无需使用可变数组。

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)

就我而言,我使用“ sortedArrayUsingComparator”对数组进行排序。看下面的代码。

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

我的目标也是

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end

您必须创建sortDescriptor,然后可以使用sortDescriptor对nsmutablearray进行排序,如下所示。

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)

这样用于嵌套对象,

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute是一个对象,该对象保存to对象,而to对象保存姓氏字符串值。

在Swift中排序数组


对于Swifty以下人员而言,这是一种非常干净的技术,可以在全球范围内实现上述目标。让我们来看一个示例自定义类,User它具有一些属性。

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

现在我们有了一个数组,需要根据createdDate升序和/或降序对数组进行排序因此,让我们添加一个用于日期比较的功能。

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

现在,让我们有一个extensionArrayUser简而言之,让我们仅为那些仅包含User对象的数组添加一些方法

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

升序用法

let sortedArray = someArray.sortUserByDate(.orderedAscending)

降序用法

let sortedArray = someArray.sortUserByDate(.orderedAscending)

相同订单的用法

let sortedArray = someArray.sortUserByDate(.orderedSame)

extension只有Array类型为
[User]||的上述方法in才可访问Array<User>

迅捷版本:5.1

如果您有一个自定义的结构或类,并希望对其进行任意排序,则应使用对指定字段进行排序的尾随闭包来调用sort()。这是一个使用自定义结构数组对特定属性进行排序的示例:

    struct User {
        var firstName: String
    }

    var users = [
        User(firstName: "Jemima"),
        User(firstName: "Peter"),
        User(firstName: "David"),
        User(firstName: "Kelly"),
        User(firstName: "Isabella")
    ]

    users.sort {
        $0.firstName < $1.firstName
    }

如果要返回排序后的数组而不是对其进行排序,请使用sorted(),如下所示:

    let sortedUsers = users.sorted {
        $0.firstName < $1.firstName
    }
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");
本文地址:http://ios.askforanswer.com/ruheduidaiyouzidingyiduixiangdensmutablearrayjinxingpaixu.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!