【发布时间】:2014-12-25 02:51:28
【问题描述】:
我们公司有数千辆(!)汽车。每辆车都有一个 GPS 设备,它会定期 (cycle) 发送其位置。
所以每个Cycle 都包含:
-
List<Cars>(发送位置的汽车——对应CycleNum) -
CycleNum循环编号
CycleNum 由服务器确定。
例如在 CycleNum=1 中,有 4 辆汽车发送了他们的位置:
我使用的类(简化)
static int TotalCycles=0;
class Car
{
public int CarId;
public int Location ;
}
class Cycle
{
public int CycleNum;
public List<Car> Cars;
public Cycle ()
{
CycleNum=(++TotalCycles);
}
}
让我们填写一些数据:
List<Cycle> LstCyclces = new List<Cycle>();
Cycle cycle =null;
cycle = new Cycle();//cycle 1
cycle.Cars = new List<Car>();
cycle.Cars.Add(new Car {CarId=1 , Location=40});
cycle.Cars.Add(new Car {CarId=2 , Location=21});
cycle.Cars.Add(new Car {CarId=3 , Location=5});
cycle.Cars.Add(new Car {CarId=4 , Location=15});
LstCyclces.Add(cycle);
cycle = new Cycle();//cycle2
cycle.Cars = new List<Car>();
cycle.Cars.Add(new Car {CarId=1 , Location=40}); //same location
cycle.Cars.Add(new Car {CarId=2 , Location=57});//changed location
cycle.Cars.Add(new Car {CarId=3 , Location=100});//changed location
cycle.Cars.Add(new Car {CarId=4 , Location=7});//changed location
cycle.Cars.Add(new Car {CarId=7 , Location=2});//new attended ( vs previous cycle)
LstCyclces.Add(cycle);
cycle = new Cycle();//cycle3
cycle.Cars = new List<Car>();
cycle.Cars.Add(new Car {CarId=1 , Location=40}); //same
cycle.Cars.Add(new Car {CarId=2 , Location=5});//changed Location
cycle.Cars.Add(new Car {CarId=4 , Location=1});//changed Location
cycle.Cars.Add(new Car {CarId=9 , Location=7});//new attended ( vs previous cycle)
LstCyclces.Add(cycle);
可视化:
如你所见:
- 一辆新车可以进入循环
- 汽车也可以从自行车上下来
- 一辆车可以改变位置(显然)
问题
我被要求:
对于特定的给定循环编号 - 查找在上一个循环中也预期的所有汽车其中:
("new Location" - "previous Location") < abs(40)
然后从 该结果集 中,找到所有汽车 PAIRS 其中:
(Car_A.Location - Car_B.Location) < abs(65)
简而言之 - 我需要所有在上一个周期也为我提供信息的汽车,而且它们距离之前的位置并没有很远,最后 - 从那些汽车 - 我需要知道哪些汽车彼此靠近.
非常重要:我不能只检查当前位置,因为我们还需要确保汽车没有离之前的位置很远。
所以根据图片:看着cycleNum=2:
在前一个周期 (1) 中也预期的汽车是 Cars:1,2,3,4。
从该结果来看:离之前位置不远的汽车:
("new Location" - "previous Location") < abs(40)
是汽车:1,2,4。
根据该结果,我需要找到现在彼此相距不远的所有汽车对:
(Car_A.Location - Car_B.Location) < abs(65):
所以结果应该是 IEnumerable:(格式无关紧要)
-
{ Car1 , Car2 , distance=17}//这两辆车之间的距离 -
{ Car1 , Car4 , distance=33}//这两辆车之间的距离 -
{ Car2 , Car4 , distance=50}//这两辆车之间的距离
//我不介意所有排列( {car1 car2} , {car2 car1} )
我尝试了什么:
var cycleToCheck=2;
//get all cars from desired cycle
var requestedCycleCars = LstCyclces.Where(c=>c.CycleNum==cycleToCheck).SelectMany(c=>c.Cars);
//get all cars from previous cycle
var previousCycleCars = LstCyclces.Where(c=>c.CycleNum==cycleToCheck-1).SelectMany(c=>c.Cars);
//intersec between those
var MyWrongIntersect =requestedCycleCars.Intersect(previousCycleCars,new MyEqualityComparer());
但我只从当前周期而不是从前一个周期获取汽车,另外 - 我需要参考当前周期和前一个周期的汽车(无需重复) - 用于计算。
另外我认为我使用SelectMany 走错了路,这应该是最快的(c#,plinq?)。我希望它可以在一个查询中。
有什么帮助吗?
Full code working online
nb ,我当然可以分阶段进行,但重复或 ToList() 对我来说是不好的方法。我希望有一个 plinq 查询
编辑
发布的解决方案在逻辑上工作正常,但性能不佳。
2 个周期,每个周期有 10,000 辆汽车:> 9 分钟!!! :
http://i.stack.imgur.com/mjLvG.jpg
我怎样才能改进它?(asparallel 没多大用)
【问题讨论】:
-
你考虑过排序吗?简单的排序可以减少您实际必须进行的实际比较的次数。目前(没有真正考虑过)我相信你的算法有
O(n^2)。 -
@Aron 你说的是
&& x.Item1.CarId < x.Item2.CarId部分吗? -
不,我的意思是
(Car_A.Location - Car_B.Location) < abs(65)部分。如果您按位置对汽车进行分类,那么显然第一辆车和最后一辆车不会位于相似的位置。尝试以一种可以快速查询的形式存储您的数据。这是数据库的基础。