Is there any possible way of sorting that array using .reduce(), .map(), .filter() methods all together?

Viewed 93

I have been struggling for a few days with that iteration. No matter what way I've used those methods I was only able to map or filter 'cars' array without further algorithms. I want to create a one array of objects, brands names, which would include drivers names, creating an array out of brand object.

I've tried mixing those methods in different ways and in different positions in my code but only thing I achieved is a mapped array with brands without array inside. I've also browsed the whole Stack to seek for a similar problem and exceptional solution.

var cars = [
    {'brand': 'Ford'},
    {'brand': 'Seat'},
    {'brand': 'Opel'},
    {'brand': 'Kia'},
    {'brand': 'Mitsubishi'},
    {'brand': 'Toyota'}
];

var drivers = [
    {'name': 'Mark',    'car': 'Seat'},
    {'name': 'John',    'car': 'Ford'},
    {'name': 'Michael', 'car': 'Kia'},
    {'name': 'Joe',     'car': 'Toyota'}
];

var assosiated = {};
console.log(assosiated);

That's what I tried of doing, but it doesn't meet my expectations:

assosiated = cars.map(function (carss) {
            var driver = drivers.filter(function (dri) {
              return carss.brand === dri.car;
      });
     return carss.brand;
}).reduce(function (prev, curr) {
    return prev + '\n' + curr;
});

I expect the output to look like this:

assosiated = {
    "Ford": [
      {"name": "John"}
  ],
    "Seat": [
      {"name": "Mark"}
  ],
    "Opel": [],
    "Kia": [
      {"name": "Michael"}
  ],
    "Mitsubishi": [],
    "Toyota": [
      {"name": "Joe"}
  ]
}

I would also like to use all of those methods written above. Any idea what can I do to sort it like that?

3 Answers

You are also dealing with Object Literals so using Array methods like .map(), .filter(), .reduce(), etc. is only part of the solution. Details commented in demo.

let cars = [
    {'brand': 'Ford'},
    {'brand': 'Seat'},
    {'brand': 'Opel'},
    {'brand': 'Kia'},
    {'brand': 'Mitsubishi'},
    {'brand': 'Toyota'}
];
let drivers = [
    {'name': 'Mark',    'car': 'Seat'},
    {'name': 'John',    'car': 'Ford'},
    {'name': 'Michael', 'car': 'Kia'},
    {'name': 'Joe',     'car': 'Toyota'}
];
// Declare empty object
let association = {};

/* 
//A - for...of loop iterates through drivers array
      Each iteration is obj = {'name':*, 'car':*}
//B - Obj association KEY = the value of 'car' obj['car']
                      VALUE = an array with an object inside
                              key='name', value = value of 'name'
*/
for (let obj of drivers) {//A
  association[obj['car']] = [{'name': obj['name']}];//B
}

/*
//A - for...of loop iterates through cars array
      Each iteration is obj = {'brand': *}
//B - if none of the keys of Object association matches the 
      values of cars array then add an empty array named as the 
      current "brand" value
*/
for (let obj of cars) { //A
  if (!Object.keys(association).includes(obj['brand'])) {//B
    association[obj['brand']] = [];
  }
}

console.log(association);

You only need to use reduce and filter

Se my example below

var cars = [
    {'brand': 'Ford'},
    {'brand': 'Seat'},
    {'brand': 'Opel'},
    {'brand': 'Kia'},
    {'brand': 'Mitsubishi'},
    {'brand': 'Toyota'}
];

var drivers = [
    {'name': 'Mark',    'car': 'Seat'},
    {'name': 'John',    'car': 'Ford'},
    {'name': 'Michael', 'car': 'Kia'},
    {'name': 'Joe',     'car': 'Toyota'}
];

var items = cars.reduce((result, {brand}) => {
    result[brand] = drivers
        .filter(({car}) => car === brand)
        .map(({name}) => ({name}));
    return result;
}, {})

console.log(items);

In your .map() function, you're just returning the car's brand. Therefore, the array returned from it would look like this:

[
    'Ford',
    'Seat',
    'Opel',
    ...
]

Which is what gets passed to your .reduce() function.

If you want an array with the format you specified, change your function to the following and it should work:

assosiated = cars.map(function (carss) {
    var driver = drivers.filter(function (dri) {
        return carss.brand === dri.car;
    });
    // return carss.brand; YOU'RE ONLY RETURNING THE BRAND
    return {carss.brand: driver}
});
Related