Home > Back-end >  Javascript - Loop two arrays inside another functional way
Javascript - Loop two arrays inside another functional way

Time:03-19

I have two arrays vehicles and routes, given below

const vehicles = [{ name: 'TukTuk', maxSpeed: 12 },
{ name: 'Bike', maxSpeed: 10 },
{ name: 'Car', maxSpeed: 20 }];

const routes = [{ name: 'routeOne' , distance: 18, allowedSpeed: 12 }
, {name: 'routeTwo',  distance: 20, allowedSpeed: 10 }];

There is this rule, the vehicle would travel in the route's allowed speed even it can ride faster

That is covered written in this function

const getTravelTime = (vehicle, route) => { 
    return route.allowedSpeed < vehicle.maxSpeed ? (route.distance / route.allowedSpeed) : (route.distance / vehicle.maxSpeed);
};

The objective is to find the fastest route and vehicle for the Journey

I have a implementation which is not functional

const getFastestJourney = (vehicles,routes) => {
    let fastestTime = Infinity; 
    let fastestRoute,fastestVehicle;
    for(let i =0;i < vehicles.length; i  ){
        for(let j=0;j< routes.length;j  ){
            let travelTime = getTravelTime(vehicles[i],routes[j]);
            if(travelTime < fastestTime){
                fastestVehicle = vehicles[i];
                fastestRoute = routes[j];
                fastestTime = travelTime;
            }
        }
    }
    return {
        route: fastestRoute,
        vehicle: fastestVehicle,
    };
};

how do I achieve that in the functional way?

CodePudding user response:

You could get an array of all combinations of vehicles and routes and their travel time and reduce this array by looking for shorter time and faster vehicle.

const
    vehicles = [{ name: 'TukTuk', maxSpeed: 12 }, { name: 'Bike', maxSpeed: 10 }, { name: 'Car', maxSpeed: 20 }],
    routes = [{ name: 'routeOne' , distance: 18, allowedSpeed: 12 }, {name: 'routeTwo',  distance: 20, allowedSpeed: 10 }],
    getTravelTime = (vehicle, route) => route.distance / (route.allowedSpeed < vehicle.maxSpeed ? route.allowedSpeed : vehicle.maxSpeed),
    result = vehicles
        .flatMap(v => routes.map(r => ({ 
            vehicle: v.name,
            maxSpeed: v.maxSpeed,
            route: r.name,
            time: getTravelTime (v, r)
        })))
        .reduce((a, b) => 
            a.time === b.time && a.maxSpeed > b.maxSpeed ||
            a.time < b.time
                ? a
                : b
        );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

Here is one way to find the fastest vehicle/route:

const vehicles = [
  {name: 'TukTuk',maxSpeed: 12},
  {name: 'Bike', maxSpeed: 10},
  {name: 'Car', maxSpeed: 20}
]

const routes = [
  {name: 'routeOne', distance: 18, allowedSpeed: 12},
  {name: 'routeTwo', distance: 20, allowedSpeed: 10}
]

function getFastestRoute(vehicles, routes) {
  let times = []

  // Calculate times for each route/vehicle combo
  routes.forEach(r => {
    vehicles.forEach(v => {
      times.push({
        route: r.name,
        vehicle: v.name,
        time: r.distance / Math.min(r.allowedSpeed, v.maxSpeed)
      })
    })
  })

  // Find fastest time and route
  let fastest = times.reduce((prev, curr) => prev.time < curr.time ? prev : curr)

  return fastest
}

console.log(getFastestRoute(vehicles, routes))

If you need all fastest vehicles and routes, you can use this instead:

let fastest = times.filter(f => f.time === Math.min(...times.map(t => t.time)))

CodePudding user response:

const vehicles = [{ name: 'TukTuk', maxSpeed: 12 },
{ name: 'Bike', maxSpeed: 10 },
{ name: 'Car', maxSpeed: 20 }];

const routes = [{ name: 'routeOne' , distance: 18, allowedSpeed: 12 }
, {name: 'routeTwo',  distance: 20, allowedSpeed: 10 }];

function fast(cars, roads){
    let maxSpeed = -1, speedIndex=0;
    for(let i in cars)
        if(maxSpeed < cars[i].maxSpeed){
            maxSpeed = cars[i].maxSpeed;
            speedIndex = i;
        }
    let minTime = Infinity, roadIndex=0;
    for(let i in roads)
        if(minTime > roads[i].distance/Math.min(roads[i].allowedSpeed, maxSpeed)){
            minTime=roads[i].distance/Math.min(roads[i].allowedSpeed, maxSpeed);
            roadIndex=i;
        }
    return [cars[speedIndex].name, roads[roadIndex].name]
}

console.log(fast(vehicles, routes))

Or if you don't like for loops

const vehicles = [{ name: 'TukTuk', maxSpeed: 12 },
    { name: 'Bike', maxSpeed: 10 },
    { name: 'Car', maxSpeed: 20 }];

const routes = [{ name: 'routeOne' , distance: 18, allowedSpeed: 12 },
    {name: 'routeTwo',  distance: 20, allowedSpeed: 10 }];

function fast(cars, roads){
    const maxSpeed = Math.max(...cars.map(e => e.maxSpeed))
    const times = roads.map(e => e.distance/Math.min(e.allowedSpeed, maxSpeed));
    const minTime = Math.min(...times)
    const carIndex = cars.findIndex(e => e.maxSpeed==maxSpeed)
    const roadIndex = times.findIndex(e => e==minTime)
    return [cars[carIndex], roads[roadIndex]]
}

console.log(fast(vehicles, routes))

  • Related