首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DbGeography计算

DbGeography计算
EN

Code Review用户
提问于 2014-01-27 04:13:36
回答 1查看 2.4K关注 0票数 2

有了以下代码,还能做得更好吗?

代码语言:javascript
复制
public object DistanceFrom(
    IEnumerable<Coordinate> coordinates) {
    IEnumerable<DbGeography> addresses = coordinates.Select(
        c =>
            DbGeography.FromText(String.Format("POINT ({0} {1})", c.Longitude, c.Latitude)));
    IEnumerable<VehicleGeography> vehicles = this.GPSInsightProvider.Query().Document.Placemarks.Select(
        p =>
            new VehicleGeography {
                DriverName = p.DriverName,
                Point = DbGeography.FromText(String.Format("POINT ({0} {1})", p.Point.Longitude, p.Point.Latitude))
            });
    ICollection<object> technicians = new List<object>();

    foreach (DbGeography address in addresses) {
        technicians.Add(vehicles.Select(
            v =>
                new {
                    DriverName = v.DriverName,
                    Distance = v.Point.Distance(address) / 1609.344
                }).Where(
            v =>
                v.Distance.HasValue).OrderBy(
            v =>
                v.Distance).Take(3).Select(
            v =>
                new {
                    DriverName = v.DriverName,
                    Distance = String.Format("{0:#.#}", v.Distance)
                }));
    }

    return technicians;
}

GPSInsightProvider解析KML并返回其对象表示形式。然后,我将其临时转换为VehicleGeography,以便为其创建一个DbGeography属性。然后,我循环遍历我正在检查的地址,然后做一个看上去很脏的计算,看看哪个是离地址最近的三辆车。最多我一次最多要做三个地址。我把得到的对象作为JSON返回到我的web应用程序中。

我很好奇是否有更好的方法来执行整个查找/计算/其他什么-这是?

EN

回答 1

Code Review用户

发布于 2014-10-30 11:29:20

首先,我真的不喜欢您的缩进,特别是方法头的缩进,所以我已经粘贴到Visual中,并将从下面的代码开始工作:

代码语言:javascript
复制
    public object DistanceFrom(IEnumerable<Coordinate> coordinates)
    {
        IEnumerable<DbGeography> addresses = coordinates.Select(c =>
            DbGeography.FromText(String.Format("POINT ({0} {1})", c.Longitude, c.Latitude)));
        IEnumerable<VehicleGeography> vehicles = this.GPSInsightProvider.Query().Document.Placemarks.Select(p =>
            new VehicleGeography
            {
                DriverName = p.DriverName,
                Point = DbGeography.FromText(String.Format("POINT ({0} {1})", p.Point.Longitude, p.Point.Latitude))
            });
        ICollection<object> technicians = new List<object>();

        foreach (DbGeography address in addresses)
        {
            technicians.Add(
                vehicles
                    .Select(v =>
                        new
                        {
                            DriverName = v.DriverName,
                            Distance = v.Point.Distance(address) / 1609.344
                        })
                    .Where(v =>v.Distance.HasValue)
                    .OrderBy(v =>v.Distance)
                    .Take(3)
                    .Select(v =>
                        new
                        {
                            DriverName = v.DriverName,
                            Distance = String.Format("{0:#.#}", v.Distance)
                        }));
        }

        return technicians;
    }

我的第一个问题是:为什么返回一个对象?我强烈反对返回匿名类型,您确实应该为这个数据组合创建一个类或结构。其次,您知道最起码,它返回这些匿名类型的列表,因此至少应该返回一个List<object>

第二:

ICollection<object> technicians = new List<object>();

为什么你要特别减少你要返回的功能?对参数要求最少,返回最多。

在右边使类型明显的变量声明上使用var。当您希望稍后更改该变量的类型时,这将节省额外的输入。

例如:

ICollection<object> technicians = new List<object>();

变成了

var technicians = new List<object>();

您是否有特殊的理由只返回查询的前3名结果?如果是这样的话,这个神奇的数字应该是一个具有合理名称的const。如果不是,它应该是一个变量,同样有一个合理的名称。

1609.344也是如此。我猜这是一种从米到英里的转换,但这本身是没有意义的。

我觉得你的LINQ做得太多了。我建议把它分开一点,这样它所做的事情就更清楚了。毕竟,你已经在遍历地址了,所以把它分开一点。

代码语言:javascript
复制
            technicians.Add(
                vehicles
                    .Select(v =>
                        new
                        {
                            DriverName = v.DriverName,
                            Distance = v.Point.Distance(address) / 1609.344
                        })
                    .Where(v =>v.Distance.HasValue)
                    .OrderBy(v =>v.Distance)
                    .Take(3)
                    .Select(v =>
                        new
                        {
                            DriverName = v.DriverName,
                            Distance = String.Format("{0:#.#}", v.Distance)
                        }));

可能会变成

代码语言:javascript
复制
            var vehiclesByDistance = 
                vehicles
                    .Select(v =>
                        new
                        {
                            DriverName = v.DriverName,
                            Distance = v.Point.Distance(address) / 1609.344
                        })
                    .Where(v =>v.Distance.HasValue)
                    .OrderBy(v =>v.Distance);

            technicians.Add(
                vehiclesByDistance
                    .Take(3)
                    .Select(v =>
                        new
                        {
                            DriverName = v.DriverName,
                            Distance = String.Format("{0:#.#}", v.Distance)
                        }));

最后,我很肯定你的LINQ打破了单一责任原则。它似乎正在执行距离单元转换、排序和格式设置。把这件事分开点也许是明智的。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/40133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档