2017-03-06 3 views
0

私はswiftでデフォルトソートアルゴリズムを使用しています。 しかし、10000(10k)レコードの場合、ipadでほぼ1分の時間がかかります。ここでSwiftで大量のテキストレコードをソートする最速のソート手法はどれですか?

private var fd: [[String:AnyObject]]? = [[String:AnyObject]]() 

は、主な問題は、その10Kを超えるデータのために60秒以上を取っている

self.fd = self.fd!.sort ({ 
(r1, r2) -> Bool in 
let t = self.headers![b.tag - 10] 
if r1[t.title] is String { 
    let dateFormatter = NSDateFormatter() 
    dateFormatter.dateFormat = "dd-MMM-yyyy" 
    if dateFormatter.dateFromString("\(r1[t.title]!)") != nil { 
     let d1 = dateFormatter.dateFromString("\(r1[t.title]!)") 
     let d2 = dateFormatter.dateFromString("\(r2[t.title]!)") 
     return d1 < d2 
    } else { 
     //return "\(r1[t.title])".localizedStandardCompare("\(r2[t.title])") == .OrderedAscending 
     return "\(r1[t.title])" < "\(r2[t.title])" 
    } 
} else if r1[t.title] is Int { 
    return Int(String(r1[t.title]!)) < Int(String(r2[t.title]!)) 
} else { 
    // return "\(r1[t.title])".localizedStandardCompare("\(r2[t.title])") == .OrderedAscending 
    return "\(r1[t.title])" < "\(r2[t.title])" 
}}) 

を昇順

self.fd = self.fd!.sort ({ (r1, r2) -> Bool in 
let t = self.headers![b.tag - 10] 
if r1[t.title] is String { 
    let dateFormatter = NSDateFormatter() 
    dateFormatter.dateFormat = "dd-MMM-yyyy" 
    if dateFormatter.dateFromString("\(r1[t.title]!)") != nil { 
     let d1 = dateFormatter.dateFromString("\(r1[t.title]!)") 
     let d2 = dateFormatter.dateFromString("\(r2[t.title]!)") 
     return d1 > d2 
    } else { 
     // return "\(r1[t.title])".localizedStandardCompare("\(r2[t.title])") == .OrderedDescending 
     return "\(r1[t.title])" > "\(r2[t.title])" 
    } 
} else if r1[t.title] is Int { 
    return Int(String(r1[t.title]!)) > Int(String(r2[t.title]!)) 
} else { 
    // return "\(r1[t.title])".localizedStandardCompare("\(r2[t.title])") == .OrderedDescending 
    return "\(r1[t.title])" > "\(r2[t.title])" 
}}) 

を降順ための私のコードです。 解決策を教えてください。

+7

'let dateFormatter = NSDateFormatter(); dateFormatter.dateFormat = "dd-MMM-yyyy" 'はクロージャの外側を移動します。常に同じですが、無駄なalloc/initと消費です。それはあなたを少し節約するはずです。 – Larme

+2

楽器でタイムプロファイラツールを試しましたか?例えば。 https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started – Mats

+0

撮影時間はhttps://github.com/RobertGummesson/BuildTimeAnalyzer-for-Xcode –

答えて

0

並べ替えの主なパフォーマンスの問題は、比較クロージャで変換を実行することです。これにより、値の書式設定プロセスが指数関数的に呼び出されます(配列のサイズに基づいて)。

これを実行するより効率的な方法は、.map()を使用して変換を1回だけ実行し、結果にソート関数を適用することです。これは、10からどこにでも行くべき

// only initialize your date formatter once 
let dateFormatter = DateFormatter() 
dateFormatter.dateFormat = "dd-MMM-yyyy" 

// Extract the appropriate value and returns it in one of 3 types 
// sorting will compare the 3 typed values knowing that only one of the 3 
// will actually differ for a given data type 
// 
// The element is returned in the tupple in order to rebuild the 
// array content after sorting on the 3 values 
func getSortValues(_ element:[String:Any], _ id:String) -> ([String:Any], String, Int, TimeInterval) 
{ 
    let value   = element[id] 
    var stringOrder = "" 
    var numericOrder = 0 
    var dateOrder  = TimeInterval(0) 

    if let stringValue = value as? String, 
     let dateValue = dateFormatter.date(from:stringValue) 
    { 
     dateOrder = dateValue.timeIntervalSinceReferenceDate 
    } 
    else if let intValue = value as? Int 
    { 
     numericOrder  = intValue 
    } 
    else if value != nil 
    { 
     stringOrder = "\(value!)" 
    } 
    return (element, stringOrder, numericOrder, dateOrder) 
} 

let columnId = headers![b.tag - 10] 
fd = fd!.map{ getSortValues($0, columnId) } 
     .sorted{ $0.1 < $1.1 || $0.2 < $1.2 || $0.3 < $1.3 } 
     .map{ $0.0 } 

:ここ

は、配列内の要素ごとに一度だけ、この抽出を実行するには、ソート値を抽出して)(.MAPする機能を使用してコードに基づく例です。 〜30倍速くなります(アレイのサイズによって異なります)。

+0

おかげで、私はそれをしようとすると、それは私のために動作するかどうかを確認します –

+0

感謝のために。答えは –

+0

です。少し遅くなるが間違いなく改善された。 –

関連する問題