2010-01-19 19 views
7

क्या उन linq अनुरोधों की दक्षता में सुधार करना संभव है? मैं दो अलग-अलग loops का उपयोग करता हूं ... क्या आप इस कोड को अनुकूलित करने में मेरी सहायता कर सकते हैं?1 लूप में 2 सरणी पर लिंक?

 double[] x = { 2, 3, 1, 5, 7, 2, 3 }; 
     double[] y = { 1, 2, 3, 4, 5, 6, 7 };    
     IEnumerable<int> range = Enumerable.Range(0, x.Length); 
     double[] y_sorted = (from n in range orderby x[n] select y[n]).ToArray(); 
     double[] x_sorted = (from n in range orderby x[n] select x[n]).ToArray(); 

की तरह है कि अगर आप पसंद करते अजगर में इस कोड है:

 x_index = argsort(x) 
     x_sorted = [x[i] for i in x_index] 
     y_sorted = [y[i] for i in x_index] 

आप देखेंगे कि, इस अजगर कोड में, मैं केवल एक ही प्रकार का उपयोग करें। यह इस सी # कोड का मामला नहीं है।

हम अंत में मिलना चाहिए:

 x_sorted = { 1, 2, 2, 3, 3, 5, 7 } 
     y_sorted = { 3, 1, 6, 2, 7, 4, 5 } 

फ्रेड

संपादित करें: मैं तो यहाँ (एक छोटे से सुधार के बाद) Diadistis के प्रोग्राम का उपयोग

हम चले: Array.Sort (x, y) (0.05)

द्वारा निम्नलिखित (0.18) का सबसे तेज़ तरीका है
 int[] x_index = Enumerable.Range(0, x.Length).OrderBy(i => x[i]).ToArray(); 
     double[] x_sorted = x_index.Select(i => x[i]).ToArray(); 
     double[] y_sorted = x_index.Select(i => y[i]).ToArray(); 

अन्य समाधान मेरे पीसी पर समय खपत में काफी समकक्ष (~ 0.35) हैं।

अगर किसी के पास कोई दिलचस्प विचार है, तो मैं इसे प्रोफाइल कर दूंगा और इस पोस्ट को अपडेट करूँगा।

+0

नहीं, यह मेरे लिए ठीक लग रहा है। क्या आपको शायद पहले वक्तव्य में 'ऑर्डरबी वाई [एन]' का मतलब था? – leppie

+1

नहीं, यह जानबूझकर था। – Frederic

+0

आपका कोड क्या करता है? – dtb

उत्तर

12

ठीक है, लेकिन मैं एक सरल वाक्य रचना पसंद करेंगे:

double[] x = { 2, 3, 1, 5, 7, 2, 3 }; 
double[] y = { 2, 3, 1, 5, 7, 2, 3 }; 

double[] x_sorted = x.OrderBy(d => d).ToArray(); 
double[] y_sorted = y.OrderBy(d => d).ToArray(); 

संपादित करें:

अरे ... मैं पहचानना है कि यह एक साहचर्य था विफल रहा है सरणी प्रकार

double[] x = { 2, 3, 1, 5, 7, 2, 3 }; 
double[] y = { 1, 2, 3, 4, 5, 6, 7 }; 

double[] y_sorted = y.Clone() as double[]; 
double[] x_sorted = x.Clone() as double[]; 

Array.Sort(x_sorted, y_sorted); 

संपादित 2 1/2

और कुछ प्रदर्शन परीक्षण:

public class Program 
{ 
    delegate void SortMethod(double[] x, double[] y); 

    private const int ARRAY_SIZE = 3000000; 

    private static Random RandomNumberGenerator = new Random(); 

    private static double[] x = GenerateTestData(ARRAY_SIZE); 
    private static double[] y = GenerateTestData(ARRAY_SIZE); 

    private static double[] GenerateTestData(int count) 
    { 
     var data = new double[count]; 

     for (var i = 0; i < count; i++) 
     { 
      data[i] = RandomNumberGenerator.NextDouble(); 
     } 

     return data; 
    } 

    private static void SortMethod1(double[] x, double[] y) 
    { 
     Array.Sort(x, y); 
    } 

    private static void SortMethod2(double[] x, double[] y) 
    { 
     IEnumerable<int> range = Enumerable.Range(0, x.Length); 
     x = (from n in range orderby x[n] select y[n]).ToArray(); 
     y = (from n in range orderby x[n] select x[n]).ToArray(); 
    } 

    private static void SortMethod3(double[] x, double[] y) 
    { 
     int[] x_index = 
      Enumerable.Range(0, x.Length).OrderBy(i => x[i]).ToArray(); 

     x = x_index.Select(i => x[i]).ToArray(); 
     y = x_index.Select(i => y[i]).ToArray(); 
    } 

    private static void SortMethod4(double[] x, double[] y) 
    { 
     int[] range = 
      Enumerable.Range(0, x.Length).OrderBy(i => x[i]).ToArray(); 

     var q = (
      from n in range 
      orderby x[n] 
      select new { First = x[n], Second = y[n] }).ToArray(); 

     x = q.Select(t => t.First).ToArray(); 
     y = q.Select(t => t.Second).ToArray(); 
    } 

    private static void SortMethodPerformanceTest(SortMethod sortMethod) 
    { 
     double[] y_sorted = y.Clone() as double[]; 
     double[] x_sorted = x.Clone() as double[]; 

     var sw = new Stopwatch(); 

     sw.Start(); 
     sortMethod.Invoke(x_sorted, y_sorted); 
     sw.Stop(); 

     Console.WriteLine(
      string.Format(
       "{0} : {1}", 
       sortMethod.Method.Name, 
       sw.Elapsed)); 
    } 

    static void Main(string[] args) 
    { 
     Console.WriteLine("For array length : " + ARRAY_SIZE); 
     Console.WriteLine("------------------------------"); 

     SortMethodPerformanceTest(SortMethod1); 
     SortMethodPerformanceTest(SortMethod2); 
     SortMethodPerformanceTest(SortMethod3); 
     SortMethodPerformanceTest(SortMethod4); 

     Console.WriteLine("Press any key to continue..."); 
     Console.ReadKey(); 
    } 
} 

और परिणाम:

 
For array length : 3000000 
------------------------------ 
SortMethod1 : 00:00:00.6088503 // Array.Sort(Array, Array) 
SortMethod2 : 00:00:07.9583779 // Original 
SortMethod3 : 00:00:04.5023336 // dtb's Linq Alternative 
SortMethod4 : 00:00:06.6115911 // Christian's Linq Alternative 
+0

'ToArray()' को कॉल करने से बचने के लिए भी जब तक कि वास्तव में आवश्यक न हो - आपको 'IENumerable ' मिलता है जो आवश्यक होने तक निष्पादन को रोकता है। Array.Sort (Array, Array) – GraemeF

+3

+1 आपके प्रोग्राम में कोई गलती है। आप हमेशा SortMethod1 को कॉल करते हैं ... – dtb

+0

के लिए – Frederic

2

आप निम्न कार्य कर सकते हैं। ध्यान में रखते हुए कि यदि आप का मतलब y [n] में leppie टिप्पणी

double[] x = { 2, 3, 1, 5, 7, 2, 3 };        
double[] y = { 2, 3, 1, 5, 7, 2, 3 }; 

Array.Sort<double>(x); 
Array.Sort<double>(y); 

अद्यतन के रूप में

सही परिणाम प्राप्त करने के लिए निम्नलिखित के रूप में होना चाहिए।

double[] x = { 2, 3, 1, 5, 7, 2, 3 }; 
    double[] y = { 1, 2, 3, 4, 5, 6, 7 }; 
    Array.Sort<double, double>(x, y); 
+0

समझते हैं यह कोड नए सरणी नहीं बनाता है। यह जगह में क्रमबद्ध करें। – affan

+0

+1; सरणी को क्लोन करें यदि मूल को बरकरार रखा जाना चाहिए। –

4

यदि मैं आपका कोड सही ढंग से पढ़ता हूं, तो आप पहले सरणी के तत्वों द्वारा दो सरणी सॉर्ट करने का प्रयास कर रहे हैं।

int[] x_index = Enumerable.Range(0, x.Length).OrderBy(i => x[i]).ToArray(); 
double[] x_sorted = x_index.Select(i => x[i]).ToArray(); 
double[] y_sorted = x_index.Select(i => y[i]).ToArray(); 

वैकल्पिक रूप से, आप tuples के एक गणनीय को दो सरणियों ज़िप सकता है और उसके बाद पहला आइटम द्वारा इस क्रमबद्ध करें::

सी # करने के लिए अपने अजगर कोड का शाब्दिक अनुवाद कुछ इस तरह होगा

var sorted = Enumerable.Zip(x, y, Tuple.Create<double, double>) 
         .OrderBy(t => t.Item1) 
         .ToArray(); 
+0

एई। मैं एक बाधा भूल गया ... मैं .net3.5 का उपयोग करता हूं (लेकिन मैं वास्तव में .net4 का उपयोग करना पसंद करूंगा !!) – Frederic

+0

आप आसानी से .NET3.5 में एक ज़िप विधि और टुपल्स को परिभाषित कर सकते हैं। – dtb

+0

ठीक है मान लें कि .NET 4 से फ़ंक्शन स्वीकार किए जाते हैं :) – Frederic

2

यह तेजी से हो सकता है के रूप में आप केवल एक बार प्रकार:

var q = 
    (from n in range 
    orderby x[n] 
    select new { First = x[n], Second = y[n] }).ToArray(); 
double[] x_sorted = q.Select(t => t.First).ToArray(); 
double[] y_sorted = q.Select(t => t.Second).ToArray(); 
+2

अच्छा; मेरे टुपल उत्तर के समान। क्यू को दो बार निष्पादित करने से रोकने के लिए आपको ToArray जोड़ने की आवश्यकता है। – dtb

+0

@ डीटीबी: धन्यवाद, आपके सुधार को शामिल किया गया। – Christian

+0

कोई विचार नहीं है कि यह गति के मामले में एक सुधार है। मैंने अभी बताया कि क्यू को दो बार निष्पादित किया गया था, जिसे मैंने सोचा था कि आप जो भी इरादा नहीं कर सकते हैं। – dtb

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