Действительно ли возможно повысить эффективность тех запросов linq? Я использую два различных цикла... Можно ли помочь мне оптимизировать этот код?
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();
Этот код в Python похож на это, если Вы предпочитаете:
x_index = argsort(x)
x_sorted = [x[i] for i in x_index]
y_sorted = [y[i] for i in x_index]
Вы заметите, что в этом коде Python я использую только один вид. это не имеет место этого кода c#.
мы должны достигнуть конец:
x_sorted = { 1, 2, 2, 3, 3, 5, 7 }
y_sorted = { 3, 1, 6, 2, 7, 4, 5 }
Fred
Править: Я использую программу Diadistis (после маленького исправления)
Таким образом, здесь мы идем: Массив. Вид (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) в потреблении времени на моем ПК.
Если у кого-то будет интересная идея, то я представлю ее и обновлю это сообщение.
Это нормально, но я бы предпочел более простой синтаксис:
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();
Редактировать:
Argh ... Я не смог занять, что это был ассоциативный массив.
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
Это Быстрее, так как вы только разбираетесь только один раз:
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();
Вы также можете выполнить следующее. Сохранение того, что если вы имеете в виду y [n], как в 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);
Обновление
, должно быть, как следует, чтобы получить правильный результат.
double[] x = { 2, 3, 1, 5, 7, 2, 3 };
double[] y = { 1, 2, 3, 4, 5, 6, 7 };
Array.Sort<double, double>(x, y);
Если я правильно прочитал ваш код, то вы пытаетесь отсортировать два массива по элементам первого массива.
Буквальное преобразование вашего кода на питонском языке в C# было бы чем-то вроде этого:
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();
Или вы могли бы застегнуть два массива в кортеж и затем отсортировать их по первому элементу:
var sorted = Enumerable.Zip(x, y, Tuple.Create<double, double>)
.OrderBy(t => t.Item1)
.ToArray();