HariHaravelan
HariHaravelan

Reputation: 1057

Javascript - Loop two arrays inside another functional way

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?

Upvotes: 1

Views: 78

Answers (3)

palmarbg
palmarbg

Reputation: 159

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))

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386654

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; }

Upvotes: 1

Timur
Timur

Reputation: 2287

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)))

Upvotes: 1

Related Questions