C# - 优化逻辑

时间:2017-08-19 17:51:46

标签: c# .net list linq

我有一个对象列表。这些对象包含其他属性中的lat和lon坐标。我想只提取满足

的thoose coordonates
(Math.Abs(elem1.lat - elem2.lat) > Delta && Math.Abs(elem1.lon - elem2.lon) > Delta)

基本上我想只提取没有坐标的对象。

使用C#LINQ有一种优雅的方法吗?

  

编辑1:

所以elem1和elem2是列表中的任何2个元素。查询产生的元素在其中任何两个之间具有更多的增量

  

编辑2:

这是我目前的代码。它按我的意愿运作:

for (int i = 0; i < companyHistory.Count; i++)
{
     var isOk = true;
     var count = zoomApprovedHistory.Count;
     for (var j = 0; j < count; j++)
     {
          if (Math.Abs(companyHistory[i].X - zoomApprovedHistory[j].X) < delta && Math.Abs(companyHistory[i].Y - zoomApprovedHistory[j].Y) < delta)
           {
                  isOk = false;
                  break;
            }
     }

      // if no other point is close add it to approved array for this zoom
      if (isOk)
        {
          zoomApprovedHistory.Add(companyHistory[i]);
         }
}
  

我该如何优化它?它具有O(n ^ 2)复杂度。寻找最快的选择

1 个答案:

答案 0 :(得分:0)

你的问题没有得到很好的解释。如果您的elem1elem2是您想要比较的单个项目,那么这非常简单。只需执行LINQ Where即可找到符合条件的项目。

Coordinates it = new Coordinates { lat = 5, lon = 5 };
var picked = list.Where(x => Math.Abs(x.lat - it.lat) < Delta && Math.Abs(x.lon - it.lon) < Delta);

另一方面,如果你的两个元素是列表中的任何两个元素,那么你会遇到一个需要澄清问题的问题。正如我在评论中提到的那样,如果您有elem1elem2elem3,并且前两个符合条件,但elem2和{{elem3 1}}匹配标准,那么这两个元素(2和3)'点击'?假设它们是,下面的解决方案将起作用。我写了一个简单的Comparer来帮助简化事情。

public class CoordinateComparer : IEqualityComparer<Coordinates>
{
    public bool Equals(Coordinates x, Coordinates y)
    {
        return (x.lat == y.lat && x.lon == y.lon);
    }

    public int GetHashCode(Coordinates obj)
    {
        unchecked
        {
            int hash = 17;
            if (obj != null)
            {
                hash = hash * 23 + obj.lat.GetHashCode();
                hash = hash * 23 + obj.lon.GetHashCode();
            }
            return hash;
        }
    }
}

public class Coordinates
{
    public int lat { get; set; }
    public int lon { get; set; }
}

class MainClass
{
    public static void Main(string[] args)
    {
        List<Coordinates> list = new List<Coordinates>();
        list.Add(new Coordinates { lat = 5, lon = 4 }); 
        list.Add(new Coordinates { lat = 4, lon = 5 });
        list.Add(new Coordinates { lat = 7, lon = 4 });
        list.Add(new Coordinates { lat = 6, lon = 3 });
        list.Add(new Coordinates { lat = 8, lon = 2 });

        double Delta = 1.1;

        List<Coordinates> results = new List<Coordinates>();
        foreach(Coordinates item in list)
        {
            // Find items that match the condition
            var matches = list.Where(x => Math.Abs(x.lat - item.lat) < Delta && Math.Abs(x.lon - item.lon) < Delta);
            // The 'item' will always match the condition with itself, which is undesirable, so remove it
            matches = matches.Except(new List<Coordinates> { item }, new CoordinateComparer());
            // Add the items that are not already in it to the results list
            results.AddRange(matches.Where(x => !results.Contains(x, new CoordinateComparer())));
        }

        foreach (Coordinates item in results)
            Console.WriteLine("Lat : {0}, Lon : {1}", item.lat, item.lon);

        Console.ReadLine();
    }   
}

请记住,如果你的纬度和经度坐标是doublefloat,它们可能是你的,你可能会在比较时遇到问题。但这是一个完全不同的问题。