एफ # कार्यान्वयन परिणामी कुंजी की संरचनात्मक तुलना का उपयोग करता है।
let sortBy keyf seq =
let comparer = ComparisonIdentity.Structural
mkDelayedSeq (fun() ->
(seq
|> to_list
|> List.sortWith (fun x y -> comparer.Compare(keyf x,keyf y))
|> to_array) :> seq<_>)
(भी तरह)
let sort seq =
mkDelayedSeq (fun() ->
(seq
|> to_list
|> List.sortWith Operators.compare
|> to_array) :> seq<_>)
दोनों Operators.compare और ComparisonIdentity.Structural.Compare बन (अंततः)
let inline GenericComparisonFast<'T> (x:'T) (y:'T) : int =
GenericComparisonIntrinsic x y
// lots of other types elided
when 'T : float = if (# "clt" x y : bool #)
then (-1)
else (# "cgt" x y : int #)
लेकिन ऑपरेटर के लिए यह करने के लिए मार्ग पूरी तरह से है इनलाइन, इस प्रकार जेआईटी कंपाइलर किसी भी अतिरिक्त विधि आमंत्रण ओवरहेड के साथ प्रत्यक्ष डबल तुलना निर्देश डालने को समाप्त कर देगा (इसके अलावा दोनों मामलों में आवश्यक) को छोड़कर व्यवसाय।
सॉर्टबी एक तुलनाकर्ता का उपयोग करता है, इसलिए अतिरिक्त वर्चुअल विधि कॉल के माध्यम से जाएगा, लेकिन मूल रूप से इसके बारे में है।
तुलनात्मक रूप से ऑर्डरबी फ़ंक्शन को समानता के लिए वर्चुअल विधि कॉल (EqualityComparer<T>.Default
का उपयोग करके) के माध्यम से जाना चाहिए, लेकिन महत्वपूर्ण अंतर यह है कि यह जगह में है और परिणामस्वरूप इसके लिए बनाए गए बफर का उपयोग करता है। तुलनात्मक रूप से यदि आप इस प्रकार एक नज़र डालेंगे तो आप देखेंगे कि यह सूची टाइप करता है (जगह में नहीं, यह StableSortImplementation का उपयोग करता है जो विलय सॉर्ट प्रतीत होता है) और उसके बाद एक नई सरणी के रूप में इसकी एक प्रति बनाता है। यह अतिरिक्त प्रतिलिपि (आपके इनपुट डेटा के आकार को देखते हुए) धीमी गति का सिद्धांत कारण है, हालांकि अलग-अलग प्रकार के कार्यान्वयन का प्रभाव भी हो सकता है।
यह कहा गया कि यह अनुमान है। यदि यह क्षेत्र प्रदर्शन शर्तों में आपके लिए चिंता का विषय है तो समय निकालने के लिए आपको प्रोफ़ाइल प्रोफ़ाइल चाहिए।
आप को देखने के लिए क्या प्रभाव छंटाई/नकल परिवर्तन इस वैकल्पिक होता चाहते हैं:
// these are taken from the f# source so as to be consistent
// beware doing this, the compiler may know about such methods
open System.Collections.Generic
let mkSeq f =
{ new IEnumerable<'b> with
member x.GetEnumerator() = f()
interface System.Collections.IEnumerable with
member x.GetEnumerator() = (f() :> System.Collections.IEnumerator) }
let mkDelayedSeq (f: unit -> IEnumerable<'T>) =
mkSeq (fun() -> f().GetEnumerator())
// the function
let sortByFaster keyf seq =
let comparer = ComparisonIdentity.Structural
mkDelayedSeq (fun() ->
let buffer = Seq.to_array seq
Array.sortInPlaceBy (fun x y -> comparer.Compare(keyf x,keyf y)) buffer
buffer :> seq<_>)
मैं बहुत बड़ी (> मिलियन) इनपुट दृश्यों लेकिन ऐसा कुछ नहीं के साथ repl के भीतर कुछ उचित प्रतिशत speedups मिल महत्ता का क्रम। आपका लाभ, हमेशा के रूप में, भिन्न हो सकता है।
आप के लिए एक वैकल्पिक समारोह जोड़ा अगर आप इसे करने की कोशिश करना चाहते हैं ... – ShuggyCoUk
आप Array.sortInPlaceBy की कोशिश की? मान लीजिए कि आपको सरणी के संशोधन को ध्यान में रखना नहीं है, यह आपकी बड़ी जीत हो सकती है (और लिनक के ऑर्डरबी से तेज़ हो सकती है। आपको इसे सरणी की तुलना में यूनिट रेटर लौटने के साथ सौदा करना होगा (लेकिन sortInPlaceFluent a = Array.sortInPlace को दें ; एक (की जगह, न्यू लाइन और इंडेंट के साथ)। हल करती है कि – ShuggyCoUk
क्यों, लेकिन यहां तक कि sortInPlaceBy साथ बातें बस के रूप में Array.sortBy साथ के रूप में धीमी गति से कर रहे हैं पर क्लूलेस लगता मैं बेसब्री से beta2 के लिए इंतजार करेंगे, उम्मीद है कि ब्रायन और टीम के बाकी कर सकते हैं कुछ निफ्टी समाधान का काम करें :) – em70