In our company there are thousands(!) of cars. each car has a GPS device which sends periodically (cycle
) its location.
So each Cycle
contains :
List<Cars>
( cars that sent location – corresponding to theCycleNum
)CycleNum
which is Cycle number
CycleNum
is determined by a server.
So for example in CycleNum=1
, 4 cars sent their location :
Classes I used ( simplification )
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);
}
}
Let's fill some data :
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);
Visualization :
As you can see :
- A new car can come in to the cycle
- A car can also get out from a cycle
- A car can change Location(obviously)
Question
I was asked to:
For a specific given cycle Number — find all Cars that were also anticipated in the previous cycle where :
("new Location" - "previous Location") < abs(40)
And from that result set , find all cars PAIRS where :
(Car_A.Location - Car_B.Location) < abs(65)
In short - I need all cars that gave me info also for the previous cycle and also they didn't go very far from their previous location and finally - from those cars - I need to know which cars are near to each other.
Very important : I can not check only current Location , because we need to make sure also that cars didn't get very far from their previous location.
So according to the picture : looking at cycleNum=2
:
The cars who anticipated also in the previous Cycle (1) were Cars: 1,2,3,4.
From that result : The cars who didn't go very far from their previous location :
("new Location" - "previous Location") < abs(40)
Were cars : 1,2,4.
From that result I need to find all pairs of car who are now not far from each other :
(Car_A.Location - Car_B.Location) < abs(65)
:
So the result should be IEnumerable: (format isn't matter )
{ Car1 , Car2 , distance=17}
//the distance between those 2 cars < 65{ Car1 , Car4 , distance=33}
//the distance between those 2 cars < 65{ Car2 , Car4 , distance=50}
//the distance between those 2 cars < 65
//I dont mind having all permutation ( {car1 car2} , {car2 car1} )
What have I tried :
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());
But I only get cars from the current cycle and not from previous cycle ,Also - I need reference both to cars from current cycle and previous cycle(without reiterating) - for calculations.
Also I think I'm on the wrong path using SelectMany
and this is suppose to be the fastest it can be(c# , plinq?). I wish it could be in one query.
Any help ?
Full code working online
nb , of course I can do it in phases , but reiterating , or ToList()'s are bad approach for me. I was hoping for a single plinq query
Edit
Posted solution works OK logically but not performantly.
2 cycles , where each has 10,000 cars : > 9min!!! :
https://i.sstatic.net/mjLvG.jpg
How can I improve it? (asparallel didnt work much)
O(n^2)
. – Shuma&& x.Item1.CarId < x.Item2.CarId
part ? – Deplorable(Car_A.Location - Car_B.Location) < abs(65)
part. If you sort the cars by location, then obviously the first car and the last car is not going to be in a similar location. Try to store your data in a form that make querying quick. That the basis of databases. – Shuma