在给定公差范围内清洁列表<double []>

时间:2016-10-03 09:53:40

标签: c# list

我有一个List,其中每个double []的长度为3.我想通过仅留下具有给定容差内的唯一元素的double []来清理此列表(向上舍入)。例如,列表如下:

1059.17 0 446.542225842081
1059.17 0 446.542564789741
1059.17 0 446.541759880305
959.167 0 579.827860527898
959.167 0 579.827847296075

对于给定的公差= 2,应该成为这个:

1059.17 0 446.54,
959.17 0 579.83,

有一种巧妙的方式可以做到这一点吗?

3 个答案:

答案 0 :(得分:1)

假设数组元素的顺序始终相同,您可以创建自己的比较器,知道如何比较双数组:

public class MyDoubleArrComparer : IEqualityComparer<double[]>
{
    public bool Equals(double[] x, double[] y)
    {
        for (int i = 0; i < x.Length; i++)
        {
            if (x[i] != y[i]) return false;
        }

        return true;
    }

    public int GetHashCode(double[] obj)
    {
        return base.GetHashCode();
    }
}

您可以创建一个辅助方法来舍入数字并删除重复项:

public static class Helper
{
    public static List<double[]> MyFilter(this List<double[]> list, int tolerance)
    {
        var result = list
            .Select(arr =>
            {
                // rounds numbers with precision that is set in tolerance variable
                arr = arr.Select(d => d = Math.Round(d, tolerance)).ToArray();
                return arr;
            }).Distinct(new MyDoubleArrComparer()) // here we use our custom comparer
            .ToList();

        return result;
    }
}

现在我们可以开始使用我们的辅助方法:

var nums = new List<double[]>()
        {
            new[] {1059.17, 0, 446.542225842081},
            new[] {1059.17, 0, 446.542564789741},
            new[] {1059.17, 0, 446.541759880305},
            new[] {959.167, 0, 579.827860527898},
            new[] {959.167, 0, 579.827847296075},
        };

var result = nums.MyFilter(2);

foreach (var arr in result)
{
    foreach (var d in arr)
    {
       Console.Write(d + " ");
    }
    Console.WriteLine();
}

输出:

1059.17 0 446.54
959.17 0 579.83

答案 1 :(得分:1)

这应该有效。它使用匿名类型的内置相等比较。

List<double[]> data = ...
int tolerance = 2;
var roundedData = data
    .Select(x => new {
        v1 = Math.Round(x[0], tolerance),
        v2 = Math.Round(x[1], tolerance),
        v3 = Math.Round(x[2], tolerance)
    })
    .Distinct()
    .Select(x => new [] { x.v1, x.v2, x.v3 })
    .ToList();

答案 2 :(得分:0)

也许这会有用吗?

public List<double[]> CleanWithTolerance(List<double[]> doubleNumbersList, int tolerance)
{
    var newDoublesNumbersList = new List<double[]>();
    foreach(double[] doubleNumbers in doubleNumbersList)
    {
        var newDoublesNumbers = doubleNumbers.Select(doubleNumber => Math.Round(doubleNumber, tolerance)).ToArray();
        if(newDoublesNumbersList.All(cleanDoubleNumbers => !Enumerable.SequenceEqual(cleanDoubleNumbers, newDoublesNumbers))
        {
            newDoublesNumbersList.Add(newDoublesNumbers);
        }
    }
    return newDoublesNumbersList;
}
相关问题