Linq on 2 arrays in 1 loop?

Is it possible to increase the efficiency of these linq queries? I use two different loops ... Can you help me optimize this code?

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(); 

This python code looks like this if you prefer:

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

You will notice that in this python code I use only one view. which is not the case with C # code.

we should get at the end:

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

Fred

Edit: I am using Diadistis program (after a little correction)

So, let's go: Array.Sort (x, y) (0,05) is the fastest way following (0.18) on

  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(); 

Other solutions are pretty equivalent (~ 0.35) in temporary consumption on my PC.

If anyone has an interesting idea, I will profile it and update this post.

+7
c # linq
source share
4 answers

This is fine, but I would prefer a simpler syntax:

 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(); 

Strike>

Edit:

Argh ... I did not notice that it was an associative array.

 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); 

Change 2 1/2

And some performance tests:

 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(); } } 

And the results:

 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 Linq Alternative
 SortMethod4: 00: 00: 06.6115911 // Christian Linq Alternative
+12
source share

If I read your code correctly, you will try to sort the two arrays using the elements of the first array.

The literal translation of your Python code in C # would be something like this:

 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(); 

Alternatively, you can archive two arrays into enumerable tuples, and then sort them by the first element:

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

You can also do the following. Given that if you meant y [n], as in the leppie comment

 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); 

Update

To get the correct result, there should be the following:

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

This can be faster since you only sort once:

 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
source share

All Articles