เรียงลำดับ NSArray ของสตริงวันที่หรือวัตถุ


86

ฉันมีNSArrayสตริงวันที่(เช่น NSString)ดังนี้ "พฤ 21 พ.ค. 52 19:10:09 น. -0700"

ฉันต้องการจัดเรียงNSArrayตามวันที่ ฉันคิดเกี่ยวกับการแปลงสตริงวันที่เป็นNSDateวัตถุก่อน แต่ติดอยู่ที่วิธีการจัดเรียงตามNSDateวัตถุ

ขอบคุณ.


ติดแท็กใหม่เนื่องจากสิ่งนี้เกี่ยวข้องกับกรอบงานพื้นฐานและไม่เฉพาะเจาะจงกับ iPhone
Quinn Taylor

คำตอบ:


110

จัดเก็บวันที่เป็นNSDateวัตถุในอาร์เรย์ NS (เปลี่ยนแปลงได้) จากนั้นใช้-[NSArray sortedArrayUsingSelector:หรือ-[NSMutableArray sortUsingSelector:]และส่งผ่าน@selector(compare:)เป็นพารามิเตอร์ -[NSDate compare:]วิธีการจะสั่งซื้อในวันที่เรียงลำดับขึ้นสำหรับคุณ สิ่งนี้ง่ายกว่าการสร้างNSSortDescriptorและง่ายกว่าการเขียนฟังก์ชันเปรียบเทียบของคุณเอง (อNSDateอบเจ็กต์รู้วิธีเปรียบเทียบกันเองอย่างน้อยก็มีประสิทธิภาพมากที่สุดเท่าที่เราจะทำได้ด้วยโค้ดที่กำหนดเอง)


11
ไม่ชัดเจนว่าคำถามเดิมถามเกี่ยวกับการจัดเรียงอาร์เรย์ของวันที่หรือการจัดเรียงอาร์เรย์ของวัตถุที่มีฟิลด์วันที่ นี่เป็นวิธีที่ง่ายที่สุดหากเป็นแบบเดิม แต่ถ้าเป็นแบบหลัง NSSortDescriptor เป็นวิธีที่จะไป
smorgan

@smorgan NSSortDescriptor จัดการกับวันที่ไม่มีอย่างไร
เถ้า

ขอบคุณสำหรับความช่วยเหลือฉันคิดว่าเราควรอ่านเพิ่มเติมใน Apple Docs แต่ดูเหมือนจะน่าเบื่อมากจนกว่าคุณจะใช้มัน
Abo3atef

1
คุณสามารถแสดงสิ่งนี้ในโค้ดตัวอย่างได้ไหม ขอบคุณล่วงหน้า.
uplearnedu.com

115

หากฉันมีNSMutableArrayวัตถุที่มีฟิลด์ "beginDate" ประเภทที่NSDateฉันใช้NSSortDescriptorดังต่อไปนี้:

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

3
ฉันรู้ว่าเวลาผ่านไปนานมาก (เมื่อคำตอบก่อนหน้าได้รับการยอมรับว่ายังไม่มี NSSortDescriptor) แต่สำหรับการใช้ในอนาคตอันนี้ควรเป็นคำตอบที่เหมาะสม
Vive

1
นี่เป็นทางออกที่ยอดเยี่ยม แก้ไขปัญหาของฉันด้วยรหัสไม่กี่บรรทัดขอบคุณตัน @vinzenzweber
Pratyusha Terli

1
จริงๆ ... ฉันตกใจมากที่ได้ผลในการวิ่งครั้งแรก! ฉันคิดว่า initWithKey สงวนไว้สำหรับพจนานุกรมที่มีการกำหนดคีย์ แต่สิ่งที่คุณต้องทำคืออ้างอิงคุณสมบัติในอาร์เรย์ของออบเจ็กต์? ให้แสงส่อง vinzenzweberskavitchski !!
whyoz

NSSortDescriptor มีมาตั้งแต่ OS X 10.3 ในปลายปี 2003 นี่เป็นสถานการณ์ที่แตกต่างกันเล็กน้อยโดยที่วันที่เป็นฟิลด์ในออบเจ็กต์อื่น ด้วย API ที่ทันสมัยยิ่งขึ้นคุณอาจใช้-[NSMutableArray sortUsingComparator:](10.6+) และส่งผ่านบล็อกที่ส่งคืนผลลัพธ์ของการเรียก-compare:ในสองฟิลด์ มันอาจจะเร็วกว่าการเรียก-valueForKey:ใช้วัตถุแต่ละชิ้น คุณสามารถใช้-sortWithOptions:usingComparator:และส่งผ่านตัวเลือกเพื่อจัดเรียงพร้อมกันได้เช่นกัน
Quinn Taylor

NSSortDescriptor ข้างต้นจัดการกับวันที่ศูนย์อย่างไร เราจำเป็นต้องบอกผู้อธิบายว่าจะทำอย่างไรกับพวกเขาถ้าเป็นเช่นนั้นอย่างไร?
เถ้า

17

คุณอาจใช้สิ่งต่อไปนี้:

//Sort the array of items by  date
    [self.items sortUsingComparator:^NSComparisonResult(id obj1, id obj2){
        return [obj2.date compare:obj1.date];
    }];

แต่ไม่คิดว่าวันที่จะถูกเก็บไว้เป็นNSDateค่อนข้างNStringซึ่งควรจะไม่มีปัญหาที่จะทำให้ / ทำ ขอแนะนำให้จัดเก็บข้อมูลในรูปแบบดิบด้วย ทำให้ง่ายต่อการจัดการในสถานการณ์เช่นนี้


9

คุณสามารถใช้บล็อกเพื่อจัดเรียงเข้าที่:

sortedDatesArray = [[unsortedDatesArray sortedArrayUsingComparator: ^(id a, id b) {
    NSDate *d1 = [NSDate dateWithString: s1];
    NSDate *d2 = [NSDate dateWithString: s2];
    return [d1 compare: d2];
}];

ฉันขอแนะนำให้คุณแปลงสตริงทั้งหมดของคุณเป็นวันที่ก่อนที่จะเรียงลำดับเพื่อไม่ให้ทำการแปลงมากกว่าที่มีรายการวันที่ อัลกอริทึมการจัดเรียงใด ๆ จะทำให้คุณได้รับการแปลงสตริงจนถึงปัจจุบันมากกว่าจำนวนรายการในอาร์เรย์ (บางครั้งอาจมากกว่านั้นมาก)

ข้อมูลเพิ่มเติมเกี่ยวกับการเรียงบล็อก: http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html


นี่คือรูปแบบหนึ่งของแนวคิดย่อยที่เหมาะสมที่สุดที่นำเสนอโดย @notoop ไม่ว่าในกรณีใดการแปลงเป็น NSDate ก่อนเป็นวิธีที่แน่นอน
Quinn Taylor

โดยทั่วไปเขาเพียงแค่ใส่คำตอบของฉันด้วยคำตอบของ @ notoop ..... ค่อนข้างไม่จำเป็นที่จะโพสต์สองครั้งหากคุณถามฉัน ....
TheCodingArt

ซึ่งช้ากว่าการแยกสตริงวันที่ลงในอาร์เรย์ของ NSDate มากจากนั้นเรียงลำดับอาร์เรย์ของ NSDate เนื่องจากจะมีการแยกวิเคราะห์สตริงเพิ่มขึ้น 2 * (n - 1) เท่า โดยทั่วไปการแยกวิเคราะห์สตริงเป็นงานที่หนักสำหรับ CPU
CarlLee

5

สิ่งที่ได้ผลในกรณีของฉันมีดังต่อไปนี้:

    NSArray * aUnsorted = [dataToDb allKeys];
    NSArray * arrKeys = [aUnsorted sortedArrayUsingComparator: ^ NSComparisonResult (id obj1, id obj2) {
        NSDateFormatter * df = [[NSDateFormatter จัดสรร] init];
        [df setDateFormat: @ "dd-MM-yyyy"];
        NSDate * d1 = [df dateFromString: (NSString *) obj1];
        NSDate * d2 = [df dateFromString: (NSString *) obj2];
        กลับ [d1 เปรียบเทียบ: d2];
    }];

ฉันมีพจนานุกรมซึ่งคีย์ทั้งหมดที่วันที่อยู่ในรูปแบบ dd-MM-yyyy และ allKeys ส่งคืนคีย์พจนานุกรมโดยไม่เรียงลำดับและฉันต้องการนำเสนอข้อมูลตามลำดับเวลา


5

คุณสามารถใช้sortedArrayUsingFunction:context:. นี่คือตัวอย่าง:

NSComparisonResult dateSort(NSString *s1, NSString *s2, void *context) {
    NSDate *d1 = [NSDate dateWithString:s1];
    NSDate *d2 = [NSDate dateWithString:s2];
    return [d1 compare:d2];
}

NSArray *sorted = [unsorted sortedArrayUsingFunction:dateSort context:nil];

เมื่อใช้ a NSMutableArrayคุณสามารถใช้sortArrayUsingFunction:context:แทนได้


9
นี่เป็นความคิดที่ไม่ดี - ฟังก์ชันการเปรียบเทียบควรเร็วและไม่ควรสร้างวัตถุ NSDate จากสตริงสำหรับการเปรียบเทียบแต่ละครั้ง หากคุณใช้ - [NSDate Compare:] อยู่แล้วเพียงแค่เก็บวันที่ในอาร์เรย์แล้วใช้ -sortedArrayUsingSelector: โดยตรง
Quinn Taylor

ฉันคิดว่านี่เป็นทางออกที่ดีถ้าคุณกำลังเรียงลำดับวัตถุที่มีฟิลด์ NSDate อยู่แล้ว ไม่?
GnarlyDog

1
หากอาร์เรย์มีNSDateวัตถุอยู่แล้วคุณสามารถใช้คำตอบของฉันด้านบนหรือแม้แต่ใช้-[NSMutableArray sortUsingComparator:]ซึ่งเพิ่มใน 10.6
Quinn Taylor

หากคุณใช้อาร์เรย์ของพจนานุกรมที่มีออบเจ็กต์คีย์ - ค่าสำหรับวันที่เป็น NSString ร่วมกับวัตถุคีย์ - ค่าอื่น ๆ โซลูชันนี้จะดีที่สุด เพียงแค่ต้องปรับเปลี่ยนเล็กน้อยภายในฟังก์ชัน dateSort ยกนิ้วให้! :)
Erfan

4

เมื่อคุณมีNSDateแล้วคุณสามารถสร้างNSSortDescriptorด้วยinitWithKey:ascending:แล้วใช้sortedArrayUsingDescriptors:เพื่อทำการเรียงลำดับ


วิธีนี้ใช้ได้ผล แต่การใช้ -sortedArrayUsingSelector: นั้นง่ายกว่าเล็กน้อยและไม่จำเป็นต้องสร้างวัตถุเพิ่มเติม
Quinn Taylor

การแก้ไขล่วงหน้าคำถามกล่าวถึง "คีย์" วันที่ "ดังนั้นฉันจึงคิดว่านี่เป็นอาร์เรย์ของวัตถุ / พจนานุกรมที่มีวันที่เป็นช่องเดียวไม่ใช่อาร์เรย์ของวันที่ดิบ ในกรณีนั้น sortedArrayUsingSelector: มีความซับซ้อนมากขึ้นเนื่องจากต้องเขียนรูทีนการจัดเรียงแบบกำหนดเองเพื่อทำการค้นหา
smorgan

ใช่ขอโทษสำหรับความสับสน - ฉันทำความสะอาดข้อมูลอ้างอิงนั้นเนื่องจากเขาแค่บอกว่าเขากำลังจัดเก็บอาร์เรย์ด้วยคีย์ 'วันที่' และฉันก็รู้ว่ามันทำให้คำถามสับสนมากขึ้น คุณถูกต้องแน่นอนเกี่ยวกับความซับซ้อนเชิงสัมพัทธ์เนื่องจากโครงสร้างข้อมูลที่ซับซ้อนมากขึ้น
Quinn Taylor


1

เปลี่ยนสิ่งนี้

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

ถึง

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

เพียงแค่เปลี่ยนคีย์: จะต้องเป็นDateเสมอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.