优化范围选择的代码

时间:2017-12-11 02:58:06

标签: c# arrays

给定一个数组和另外两个数组,我需要找到第一个数组中的元素范围

例如MainArray = {2,4,6,5,8,9},range1 = {4,5,6},range2 = {6,9,8}

for First-Iteration我必须在MainArray中选择范围[4,6]中的元素 - > [4,6,5] - [3]是输出

for second-Iteration我必须在范围[5,9]中选择MainArray中的元素 - > [5,8,9] - [3]是输出

for third-Iteration我必须在MainArray中选择范围[6,8]中的元素 - > [6,8] - [2]是输出

数组返回[3,3,2]

static void Main(string[] args)
    {

        var rng = new Random();

        var result = processFunc(Enumerable.Range(0, 5000000).OrderBy(x => rng.Next()).ToArray(),
            Enumerable.Range(0, 20000).OrderBy(x => rng.Next()).Take(200).ToArray(),
            Enumerable.Range(0, 20000).OrderBy(x => rng.Next()).Take(200).ToArray());
    }
    public static int[] processFunc(int[] scores,int[] l,int[] r)
    {
        IList<int> output = new List<int>();
        for (int i = 0; i < l.Length; i++)
        {
            var bestMatch = scores.Where(x => x >= l[i] && x <= r[i]);
            output.Add(bestMatch.Count());
        }

        return output.ToArray();
    }

当数字很小时代码运行正常但是一旦它们> 50,000,程序就会变慢。如何优化此解决方案?

1 个答案:

答案 0 :(得分:2)

假设lr具有相同的长度,请考虑以下方法:

public static int[] processFunc(int[] scores, int[] l, int[] r)
{
    var min = Math.Min(l.Min(z => z), r.Min(z => z));
    var max = Math.Max(l.Max(z => z), r.Max(z => z));

    var grouped = scores.Where(z => z >= min && z <= max).GroupBy(z => z).Select(val => Tuple.Create(val.Key, val.Count())).OrderBy(z => z.Item1).ToList();

    return l.Zip(r, (left, right) =>
    {
        var matching = grouped.Where(z => z.Item1 >= left).TakeWhile(z => z.Item1 <= right);
        return matching.Sum(z => z.Item2);
    }).ToArray();
}

minmax用于忽略不相关(太大或太小)的数字。 grouped用于预先计算计数并按顺序排列。 Zip用于排列lr值并将计数汇总在一起。

这个解决方案在我的机器上比原始代码快大约2-3倍(剩下的大部分时间实际上是设置参数,而不是在函数本身中。)

相关问题