2014-11-03 12 views
5

मेरे पास स्विफ्ट ऑब्जेक्ट्स की एक सूची है जिसे मैं कई मानदंडों से सॉर्ट करना चाहता हूं। सूची में वस्तुओं प्रकार DateRange के होते हैं:मैं कई मानदंडों द्वारा स्विफ्ट ऑब्जेक्ट्स को कैसे क्रमबद्ध करूं

class DateRange { 
    var from: NSDate? 
    var to: NSDate? 
} 

सूची इन वस्तुओं जहां कुछ from या to क्षेत्रों शून्य कर रहे हैं के कई शामिल हैं।

  1. पहले सभी वस्तुओं है कि दिनांक
  2. फिर वस्तुओं है कि कम से कम एक तारीख (या तो from या to)
  3. और बहुत अंत वस्तुओं पर बिना किसी भी
  4. : मैं इस सूची के अनुसार क्रमबद्ध है करना चाहते हैं

तिथियां स्वयं ही कोई फर्क नहीं पड़ता, केवल उनके अस्तित्व। रूबी में मैं ऐसा कर सकता है (अगर तारीख nil है मैं इसे एक बहुत कम तिथि पर सेट):

date_ranges.sort { |a, b| 
    [fix_nil(a.from), fix_nil(a.to)] <=> [fix_nil(b.from), fix_nil(b.to)] 
}.reverse 

def fix_nil(val) 
    val.nil? ? Date.new(0) : val 
end 

स्विफ्ट के साथ यह करने के लिए सबसे अच्छा तरीका क्या है? अग्रिम में धन्यवाद।

उत्तर

2

यह की तरह लगता है हो सकता है dateCount गणना की गई संपत्ति को DateRange प्रकार में जोड़ने का अच्छा विचार हो।

extension DateRange { 
    // returns the number of non-nil NSDate members in 'from' and 'to' 
    var dateCount: Int { 
     switch (from, to) { 
     case (nil, nil): return 0 
     case (nil, _): return 1 
     case (_, nil): return 1 
     default: return 2 
     } 
    } 
} 

तो फिर तुम एक सरल बंद के साथ अपनी सूची सॉर्ट कर सकते हैं: यह पैटर्न मिलान के लिए एक अच्छा समय होगा

var ranges = [DateRange(nil, nil), DateRange(NSDate(), nil), DateRange(nil, NSDate()), DateRange(nil, nil), DateRange(NSDate(), NSDate())] 
ranges.sort { $0.dateCount > $1.dateCount } 

यदि आप चाहते हैं तो आप भी यह Comparable कुछ और लाइनों के साथ कर सकता है :

extension DateRange : Comparable { } 
func ==(lhs: DateRange, rhs: DateRange) -> Bool { 
    return lhs.dateCount == rhs.dateCount 
} 
func <(lhs: DateRange, rhs: DateRange) -> Bool { 
    return lhs.dateCount > rhs.dateCount 
} 

यह आपको तरह अपनी सूची की सुविधा देता है ठीक से एक ऑपरेटर तर्क के साथ:

ranges.sort(<) 
+0

पैटर्न मिलान के लिए महान उपयोग केस, आपकी मदद के लिए धन्यवाद! –

1

मुझे लगता है कि सूची द्वारा आप सरणी मतलब है, इसलिए मुझे लगता है कि इस धारणा पर मेरा उत्तर आधारित कर रहा हूँ।

(lhs: T, rhs: T) -> Bool 

लौटने truelhs अगर है rhs कम से कम, झूठी अन्यथा:

आप सरणी struct के sort विधि है, जो एक बंद इस हस्ताक्षर होने लगते हैं का उपयोग कर सकते हैं।

मैं इस कार्यान्वयन के साथ आया था:

var x: [DateRange] 
// ... initialize the array 

x.sort { (lhs: DateRange, rhs: DateRange) -> Bool in 
    if lhs.from != nil && lhs.to != nil { 
     return true 
    } 

    if lhs.from == nil && lhs.to == nil { 
     return false 
    } 

    return rhs.from == nil && rhs.to == nil 
} 
  • अगर lhs दोनों गुण नहीं के बराबर नहीं है, तो यह पहले आता है, rhs
  • अगर lhs दोनों गुण शून्य, तो अगर बाद आता है की परवाह किए बिना rhs
  • अन्य lhs में एक शून्य है, दूसरा शून्य नहीं है, और उस स्थिति में यह केवल तभी आता है जब rhs में दोनों गुण शून्य हों

आप कई स्थानों में sort पुन: उपयोग करने की योजना है, यह sort विधि से बाहर ले जाने के लिए कोड बेहतर है - सबसे अच्छी जगह शायद < ऑपरेटर की एक अधिभार है:

func < (lhs: DateRange, rhs: DateRange) -> Bool { 
    if lhs.from != nil && lhs.to != nil { 
     return true 
    } 

    if lhs.from == nil && lhs.to == nil { 
     return false 
    } 

    return rhs.from == nil && rhs.to == nil 
} 

और में उस मामले का उपयोग इस प्रकार किया जा सकता है:

x.sort(<) 

यदि आप ऑपरेटर अधिभार पसंद नहीं करते हैं, तो आप निश्चित रूप से उस समारोह को किसी अन्य नाम दे सकते हैं।

ध्यान दें कि सॉर्टिंग जगह पर किया गया है।

+0

मुझे लगता है कि आपकी तुलना में एक बग है - यह दो बराबर 'डेटरेंज' उदाहरणों की तुलना करते समय सत्य वापस आ जाएगा यदि वे दोनों (शून्य, शून्य) 'हैं। –

+0

इसे दूसरे द्वारा कवर किया जाना चाहिए यदि: यदि lhs दोनों शून्य हैं, तो यह झूठा – Antonio

+0

क्षमा करें - मुझे वह पिछला मिला है। यदि दोनों श्रेणियों में दोनों तिथियां हैं, तो यह सच हो जाएगा क्योंकि पहली शर्त केवल 'lhs' को देख रही है। –

1

यहां यह है कि मैं इस से कैसे संपर्क करूंगा। चीजों को सरल रखने के लिए, तिथि सीमा के लिए स्कोरिंग फ़ंक्शन जोड़ें।

शून्य & शून्य: अपने परिदृश्य में, आप 3 संभावनाएं है 0 अंक

शून्य & तारीख: 1 अंक

तारीख & तारीख: 2 अंक

import Foundation 

class DateRange { 
    var from: NSDate? 
    var to: NSDate? 

    init(from: NSDate?, to: NSDate?) 
    { 
     self.from = from 
     self.to = to 
    } 

    func scoreDateRange() -> Int 
    { 
     var score = 0 
     if from != nil 
     { 
      score++ 
     } 
     if to != nil 
     { 
      score++ 
     } 
     return score 
    } 
} 

func sortDateRange(d1 : DateRange, d2 : DateRange)-> Bool 
{ 

    return d1.scoreDateRange() > d2.scoreDateRange() 
} 

var date_ranges = [DateRange]() 
date_ranges.append(DateRange(from:nil, to:nil)) 
date_ranges.append(DateRange(from:nil, to:nil)) 
date_ranges.append(DateRange(from:NSDate(), to:NSDate())) 
date_ranges.append(DateRange(from:nil, to:NSDate())) 
date_ranges.append(DateRange(from:NSDate(), to:nil)) 
date_ranges.append(DateRange(from:NSDate(), to:NSDate())) 

date_ranges.sort(sortDateRange) 
+0

स्कोरिंग फ़ंक्शन के साथ अच्छा विचार, आपके त्वरित उत्तर के लिए धन्यवाद! –

संबंधित मुद्दे