【问题标题】:C# - optimize logic [closed]C# - 优化逻辑
【发布时间】:2017-08-19 17:51:45
【问题描述】:

我有一个对象列表。这些对象包含纬度和经度坐标以及其他属性。我只想提取那些满足的坐标

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

基本上我只想提取坐标不接近的对象。

C# LINQ 有没有一种优雅的方法来做到这一点?

编辑 1:

所以 elem1 和 elem2 是列表中的任意 2 个元素。查询将导致的 I 元素在其中任意 2 个元素之间具有大于 delta 的值

编辑 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) 复杂度。寻找最快的选择

【问题讨论】:

  • 你的 elem1 和 elem2 是什么?如果这些是列表中的任何两个元素,则您的问题需要改进。想想看;两个对象可能不符合您的标准,但是这两个对象中的一个,比如 elem2,可能符合另一个不同元素的标准。你选 elem2 还是不选?
  • 您说“所有元素”,但随后您展示了一个示例,显示了看起来像 2 个不同的元素,请解释更多/更好地说明您想要实现的目标。
  • 您的方程式显示了 彼此接近的元素,但您的问题表明您想要 的元素。您想要靠近 每个 其他元素的元素、靠近 至少一个 其他元素的元素、远离其他所有元素的元素还是远离其他元素的元素至少还有一个其他元素?
  • 假设你有这些 lons 10.0 10.2 10.4 10.6 10.8 11.0 具有相同的 lats 和 delta=0.3,你想删除所有项目吗?(项目 n 太靠近项目 n+1) 或 10.0 10.4 10.8 是一个解决方案吗?或者10.2 10.6 11.0 是另一种解决方案吗?还是只满足于10.0 and 11.0?为什么?不清楚你在问什么?

标签: c# .net list linq


【解决方案1】:

您的问题措辞不好。如果您的 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,并且如果前两个不符合标准,但如果 elem2elem3 符合标准,那么是这两个元素(2和3)“命中”?假设它们是,下面的解决方案将起作用。我写了一个简单的比较器来帮助简化事情。

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(它们可能是),那么您在比较时可能会遇到问题。但这是一个完全不同的问题。

【讨论】:

  • @downvoter 为什么?介意先解释一下吗?
  • 我的猜测是 OP 否决了您对模糊问题的回答,因为这不是模糊想要的确切答案,因为同样的事情也发生在我身上。我赞成抵消。
  • @DaxFohl 我希望这不是真的,因为那很愚蠢。这个问题本身是非常模棱两可的,所以回答不是预期的不是投反对票的理由。
  • @DaxFohl OP 不能投票(他们没有足够的代表)。我猜你和 Sach 因猜测以回答一个模糊不清的问题而被否决
  • 天啊,我当然没有拒绝你的回答
猜你喜欢
  • 2015-03-26
  • 2012-04-21
  • 2012-08-10
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2019-05-07
相关资源
最近更新 更多