首先要制定一些限制措施。由于我正在编写这个环境,我无法创建自己的类或方法。只是基本的程序代码。它在CMS中,我的代码在方法本身内执行。
这是我的问题
在此页面上,我进行数据库查询,加载所有700个商店位置。然后,我根据查询字符串中的lat和lng值与数据库中的lat和lng值进行距离计算,以查找50公里范围内的商店。每一个都在该距离内,我目前添加到List<DataRow>
。我还获取距离结果,将其四舍五入到一个小数位,并将其存储到Double类型的简单列表中。我想要做的,基本上是排序这些,所以当我输出商店+距离值时,它排序最短到最长距离。我在考虑将List<DataRow>
和List<Double>
组合切换为Dictionary<Double, DataRow>
并在那里使用排序,但当然有些情况下两个地方具有相同的距离值,因此它会不是唯一的。我可以使用另一种类型的集合类型,或者你能推荐一种好的方法对数据进行排序吗?
以下是我需要视觉的代码:
PRA对象基本上是我们用于处理CMS后端方面的主要对象。在这种情况下,我使用简写方法查询数据,并检查请求数据中的几个变量。其余的都是内置的.net东西。
List<DataRow> locationsInRange = new List<DataRow>();
List<Double> distances = new List<Double>();
if(!String.IsNullOrEmpty(PRA.Request.QueryString["lat"]) && !String.IsNullOrEmpty(PRA.Request.QueryString["lng"])) {
Double earthRadius = 6371.0;
Double maxDistance = 50.0;
var locations = PRA.QueryDataRows("*", "", "{Location}", "showweb");
Double lat = Double.Parse(PRA.Request.QueryString["lat"]);
Double lng = Double.Parse(PRA.Request.QueryString["lng"]);
if(!String.IsNullOrEmpty(PRA.Request.QueryString["radius"])) {
Double temp = Double.Parse(PRA.Request.QueryString["radius"]);
if(temp > 0) {
maxDistance = temp;
}
}
bool firstError = true;
foreach(var l in locations) {
Double latSecond = 0.0;
Double lngSecond = 0.0;
try {
latSecond = Double.Parse(l["lat"].ToString());
lngSecond = Double.Parse(l["lng"].ToString());
}
catch(Exception ex) {
// do nothing. The lat and lng may not of been valid or not returned a result
}
Double dLat = Math.PI * ((lat - latSecond) / 180.0);
Double dLon = Math.PI * ((lng - lngSecond) / 180.0);
Double lat1 = Math.PI * (latSecond / 180.0);
Double lat2 = Math.PI * (lat / 180.0);
Double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
Double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
if(earthRadius * c <= (Double) maxDistance) {
locationsInRange.Add(l);
distances.Add(Math.Round(earthRadius * c, 1));
}
}
}
答案 0 :(得分:2)
使用由Tuple
类型...
var locations = new List<Tuple<DataRow, double>>();
locations.Add(Tuple.Create(row, distance));
locations.Sort((x, y) => x.Item2.CompareTo(y.Item2));
答案 1 :(得分:1)
您可以在方法中间使用var关键字来让编译器生成匿名类。
var combinedInstance = new {Row = new DataRow(), Distance = 0.0m};
您可以在方法的中间使用lambda表示法来让编译器生成新方法。
Func<Location, Location, decimal> getDistance = (loc1, loc2) =>
{
return 0.0m; //TODO implement
}
var combinedList = locationsInRange
.Select((row, i) => new {Row = row, Distance = distances[i]})
.OrderBy(x => x.Distance)
.ToList();
// now replace the original lists with newly ordered lists.
locationsInRange = combinedList.Select(x => x.Row).ToList();
distances = combinedList.Select(x => x.Distance).ToList();
答案 2 :(得分:0)
干净的方法是创建一个ICompareable
类,其中包含DataRow
和Double
,其比较默认为Double
的比较。然后,您可以使用SortedList
进行自然表示。
由于这种干净的方式根据应用程序的设计(我的第一次覆盖)是不可能的,我们需要一种肮脏的方式,我的建议是
String.Format("{0:0000000000}/{1}",Math.Round(distance*10000),unique_criterium)
答案 3 :(得分:0)
如果不能将重构转换为单个数据类型,则可以对索引进行排序并使用查找表。这足以与一些遗留代码库接口。
独立示例:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Some disjoint datasets
List<int> scores = new List<int>{3,5,2,8,4};
List<string> names = new List<string>{"three","five","two","eight","four"};
// Sequence of indices
List<int> indices = new List<int>(System.Linq.Enumerable.Range(0, scores.Count));
// Sort indices, based on corresponding score
indices.Sort(delegate(int a, int b) { return scores[a] - scores[b]; });
for(int i = 0; i < indices.Count; ++i)
{
// Use lookup table for indices
int index = indices[i];
Console.WriteLine(string.Format("Name: {0}, score: {1}", names[index], scores[index]));
}
}
}