I have a large javascript array of some people Bought a car in different years.
the simplified array is like this:
const owners = [{
name: "john",
hasCar: true,
yearBought: 2002
}, {
name: "john",
hasCar: true,
yearBought: 2005
}, {
name: "mary",
hasCar: true,
yearBought: 2015
}, {
name: "john",
hasCar: true,
yearBought: 2018
}]
if a person has more than one car (like John in this example), there is different objects for him with different years he has bought the car. I want to merge objects belongs to each individual person and the final result should be like this:
const owners = [{
name: "john",
hasCar: true,
yearBought: [2002, 2005, 2018]
}, {
name: "mary",
hasCar: true,
yearBought: 2018
}]
You could use reduce the array and group them based on name first. The accumulator is an object with each unique name as key. If the name already exists, use concat to push them into the array. Else, create a new key in the accumulator and set it to the current object. Then, use Object.values() to get the values of the array as an array
const owners = [{name:"john",hasCar:!0,yearBought:2002},{name:"john",hasCar:!0,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:!0,yearBought:2018}];
const merged = owners.reduce((r, o) => {
if(r[o.name])
r[o.name].yearBought = [].concat(r[o.name].yearBought, o.yearBought)
else
r[o.name] = { ...o };
return r;
},{})
console.log(Object.values(merged))
Just use reduce:
const owners = [{name:"john",hasCar:true,yearBought:2002},{name:"john",hasCar:true,yearBought:2005},{name:"mary",hasCar:true,yearBought:2015},{name:"john",hasCar:true,yearBought:2018}];
const newOwners = Object.values(owners.reduce((acc, curr) => {
acc[curr.name] = acc[curr.name] ? { ...acc[curr.name], yearBought: [].concat(acc[curr.name].yearBought, curr.yearBought) } : curr;
return acc;
}, {}));
console.log(newOwners);
I hope this help using PURE lodash functions.. it looks clean and readable.
var array = [{
name: "john",
hasCar: true,
yearBought: 2002
}, {
name: "john",
hasCar: true,
yearBought: 2005
}, {
name: "mary",
hasCar: true,
yearBought: 2015
}, {
name: "john",
hasCar: true,
yearBought: 2018
}]
function mergeNames(arr) {
return Object.values(_.chain(arr).groupBy('name').mapValues((g) => (_.merge(...g, {
yearBought: _.map(g, 'yearBought')
}))).value());
}
console.log(mergeNames(array));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
Thanks :)
You can group the items with a unique key (name in your case), then map the groups, and merge the items in each group:
const { flow, partialRight: pr, groupBy, map, mergeWith, concat, isUndefined } = _
const mergeDuplicates = (isCollected, key) => flow(
pr(groupBy, key), // group by the unique key
pr(map, group => mergeWith({}, ...group,
(o, s, k) => isCollected(k) && !isUndefined(o) ? concat(o, s) : s
)) // merge each group to a new object
)
const owners = [{name:"john",hasCar:true,yearBought:2002},{name:"john",hasCar:true,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:true,yearBought:2018}]
const isCollected = key => key === 'yearBought'
const result = mergeDuplicates(isCollected, 'name')(owners)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
And the lodash/fp version:
const { flow, groupBy, map, mergeAllWith, cond, nthArg, concat } = _
const mergeDuplicates = (isCollected, key) => flow(
groupBy(key),
map(mergeAllWith(cond([[
flow(nthArg(2), isCollected),
concat,
nthArg(1)
]])))
)
const owners = [{name:"john",hasCar:!0,yearBought:2002},{name:"john",hasCar:!0,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:!0,yearBought:2018}]
const isCollected = key => key === 'yearBought'
const result = mergeDuplicates(isCollected, 'name')(owners)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
Related
This function takes an array of driver objects as the first argument and a JavaScript object that specifies an attribute and corresponding value.
For example, exactMatch(drivers, { revenue: 3000 }) will return all drivers whose revenue attribute equals 3000, and exactMatch(drivers, { name: 'Bob' }) will return all drivers whose name attribute equals Bob.
I have tried setting it up with map and filter with no success. Im trying to rewrite this code using ES6 format with map or filter, or otherwise just refactor for better code. Any help would be appreciated! I am very new to programming and JS in general.
function exactMatch(drivers, obj){
const driverMatch = [];
for (const driver of drivers){
for (const key in obj){
if (driver[key] === obj[key]){
driverMatch.push(driver);
}
}
}
return driverMatch;
}
Refactor for better code and to use JS ES6.
I would just generate a predicate from the second parameter. Since it contains a keys and a values, then Object.entries will de-compose it into those and you can generate a predicate from it that simply runs Array#every on each key-value pair to check if an object matches each of those:
const makePredicate = template => {
const keyValues = Object.entries(template);
return obj => keyValues.every(([key, value]) => obj[key] === value)
}
const predicate = makePredicate({name: "Bob"});
const a = {name: "Alice"};
const b = {name: "Bob"};
console.log(predicate(a));
console.log(predicate(b));
So you can use this predicate in Array#filter directly afterwards:
const makePredicate = template => {
const keyValues = Object.entries(template);
return obj => keyValues.every(([key, value]) => obj[key] === value)
}
const drivers = [{
name: "Alice",
revenue: 20000,
colour: "red"
},
{
name: "Bob",
revenue: 10000,
colour: "blue"
},
{
name: "Carol",
revenue: 10000,
colour: "red"
}
]
console.log(drivers.filter(makePredicate({
name: "Bob"
})));
console.log(drivers.filter(makePredicate({
revenue: 10000,
colour: "red"
})));
If you want to only match at least one of the key-values supplied, then you can swap and use Array#some:
const makePredicate = template => {
const keyValues = Object.entries(template);
return obj => keyValues.some(([key, value]) => obj[key] === value)
// ^^^^
}
const drivers = [{
name: "Alice",
revenue: 20000,
colour: "red"
},
{
name: "Bob",
revenue: 10000,
colour: "blue"
},
{
name: "Carol",
revenue: 10000,
colour: "red"
}
]
console.log(drivers.filter(makePredicate({
name: "Bob"
})));
console.log(drivers.filter(makePredicate({
revenue: 10000,
colour: "red"
})));
Short answer:
function exactMatch(drivers, obj) {
return drivers.filter(driver => {
const truths = Object.keys(obj).map(k => driver[k] === obj[k])
return truths.filter(Boolean).length === truths.length
})
}
There are several ways you could do this, but this was the first way that came to me. This is assuming you could pass an obj like { name: 'Bob', salary: 20000 } and require both of those conditions to be true.
You could get the entries of obj in advance and filter the array and check with Array#some, if one key/value pair match.
// one property match
function exactMatch(drivers, obj) {
var entries = Object.entries(obj);
return drivers.filter(driver => entries.some(([k, v]) => driver[k] === v));
}
For all properties who should match, you could take Array#every.
// all properties have to match
function exactMatch(drivers, obj) {
var entries = Object.entries(obj);
return drivers.filter(driver => entries.every(([k, v]) => driver[k] === v));
}
const exampleData = {
drivers: [
{
name: 'Bob',
revenue: 5000,
},
{
name: 'Alice',
revenue: 3000
},
{
name: 'Allen',
revenue: 4000
},
{
name: 'Monkey',
revenue: 5000
}
]
};
// Finds the first occurance
function exactMatch(exampleData, target) {
const targetKey = Object.keys(target)[0]
const targetValue = Object.values(target)[0]
return exampleData.drivers.find(driver => driver[targetKey] === targetValue)
}
// Finds all of the data that met the condition
function matchAll(exampleData, target) {
const targetKey = Object.keys(target)[0]
const targetValue = Object.values(target)[0]
return exampleData.drivers.filter(driver => driver[targetKey] === targetValue)
}
const resultA = exactMatch(exampleData, {revenue: 4000})
console.log(resultA)
const resultB = matchAll(exampleData, {revenue: 5000})
console.log(resultB)
I have an object:
{
1: {
name: 'Adam',
age: 12,
},
2: {
name: 'Michal',
age: 14,
},
3: {
name: 'Jozef',
age: 12,
}
}
I tried using function filter from lodash:
this.knowledges = _.filter(this.knowledges, function (item) {
if (item.category[1] !== undefined) {
return arrayOfNumbers.indexOf(item.category[1].category_id) >= 0
}
})
Variable arrayOfNumbers return array: [1,3]
so function filter should return:
{
1: {
name: 'Adam',
age: 12,
},
3: {
name: 'Jozef',
age: 12,
}
}
But it returns only first index:
{
1: {
name: 'Adam',
age: 12,
}
}
How can I fix it ?
With lodash you can use _.pick(). Pick takes an object, and an array of properties, and generates a new object with the selected properties:
const knowledges = {1:{name:"Adam",age:12,},2:{name:"Michal",age:14,},3:{name:"Jozef",age:12,}}
const arrayOfNumbers = [1,3]
const result = _.pick(knowledges, arrayOfNumbers)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
The _.pickBy() method works identically to filter for objects, so you can query the objects values, when you decide what to keep.
In this examples, I use _.pickBy() to keep all items with age === 12:
const knowledges = {1:{name:"Adam",age:12,},2:{name:"Michal",age:14,},3:{name:"Jozef",age:12,}}
const result = _.pickBy(knowledges, o => o.age === 12)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
You could use pickBy like this:
const knowledges = {1:{name:"Adam",age:12,},2:{name:"Michal",age:14,},3:{name:"Jozef",age:12,}},
arrayOfNumbers = [1,3],
result = _.pickBy(knowledges, (v, k) => arrayOfNumbers.includes(+k));
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
In vanilla JS, you could filter the the entries of the object and create an object using Object.fromEntires() like this:
const knowledges={1:{name:"Adam",age:12,},2:{name:"Michal",age:14,},3:{name:"Jozef",age:12,}},
arrayOfNumbers=[1,3];
const newObject = Object.fromEntries(
Object.entries(knowledges).filter(([k, v]) => arrayOfNumbers.includes(+k))
)
console.log(newObject)
I'm trying to transform my array so that its easily used while rendering views
I have this sample code for now
let arr = [
{
date: d.setDate(d.getDate() - 1),
name: "john",
country: "AU",
text: "Hey"
},
{
date: d.setDate(d.getDate() - 1),
name: "jake",
country: "US",
text: "Hey"
},
{
date:d.setDate(d.getDate() - 3),
name: "jeff",
country: "US",
text: "Hey"
},
{
date:d.setDate(d.getDate() - 5),
name: "jared",
country: "US",
text: "Hey"
},
{
date:d.setDate(d.getDate() - 2),
name: "jane",
country: "UK",
text: "Hey"
}
]
let hours = _.groupBy(arr, (result) => moment(result['date']).startOf('hour').format("LT"));
let day = _.groupBy(arr, (result) => moment(result['date']).startOf('day').format("MMM Do YY"));
console.log(day)
What i want is to group the data by hours which is grouped by days from a single "date" string (i can do that seperately via _.groupby function but i want it to output a combined array.
The desired output should be something like this :
{
'Apr 15th 19': [
{'4 pm':[
{
date: 1555318593445,
name: 'ahmed',
country: 'AU',
text: 'Hey'
}
]
]
}....
Use _.flow() to create a function that groups by the day, and then maps each days values, and groups them by the hour:
const { flow, groupBy, mapValues } = _
const fn = flow(
arr => groupBy(arr, v => moment(v.date).startOf('day').format("MMM Do YY")),
groups => mapValues(groups, g => _.groupBy(g, v =>
moment(v.date).startOf('hour').format("LT")
))
)
const arr = [{"date":1555318593445,"name":"john","country":"AU","text":"Hey"},{"date":155531859300,"name":"jake","country":"US","text":"Hey"},{"date":1555316593445,"name":"jeff","country":"US","text":"Hey"},{"date":1555316593345,"name":"jared","country":"US","text":"Hey"},{"date":155531659400,"name":"jane","country":"UK","text":"Hey"}]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
And the terser lodash/fp version:
const { flow, groupBy, mapValues } = _
const fn = flow(
groupBy(v => moment(v.date).startOf('day').format("MMM Do YY")),
mapValues(_.groupBy(v => moment(v.date).startOf('hour').format("LT")))
)
const arr = [{"date":1555318593445,"name":"john","country":"AU","text":"Hey"},{"date":155531859300,"name":"jake","country":"US","text":"Hey"},{"date":1555316593445,"name":"jeff","country":"US","text":"Hey"},{"date":1555316593345,"name":"jared","country":"US","text":"Hey"},{"date":155531659400,"name":"jane","country":"UK","text":"Hey"}]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
Comments Q&A:
How is flow different from chain?
Flow generates a function that runs the code in a sequence and passes the results of one function call to the next one. The lodash chain runs the code, but tries to make lazy evaluation, and combines several calls to a single one, which means that a chain of .map.filter will only iterate the array once.
However, the laziness comes with a price, you need to import the entire lodash module for it to work. While using flow, you can import just the functions that you need.
why mapvalues was the second step?
The result of the 1st group is an object { date: {}, date: {} ), and you need to group each the object values by itself. To do so you need to map the values of each date, and group them by the hour.
I have seen some questions that might look similar but none is the solution in my case. I want to regroup and recreate my array the way that it is arranged or grouped based on one of my values(age). I want to have all data of the same "age" in one place. So here is my sample array:
[
{
"age": 15,
"person": {
name: 'John',
hobby: 'ski'
},
},
{
"age": 23,
"person": {
name: 'Suzi',
hobby: 'golf'
},
},
{
"age": 23,
"person": {
name: 'Joe',
hobby: 'books'
}
},{
"age": 25,
"person": {
name: 'Rosi',
hobby: 'books'
}
},{
"age": 15,
"person": {
name: 'Gary',
hobby: 'books'
}
},
{
"age": 23,
"person": {
name: 'Kane',
hobby: 'books'
}
}
]
And I need to have an array that kind of have age as a key and person as value, so each key could have multiple values meaning the value will kind of be an array itself.
I have read this and this questions and many more but they were not exactly the same.
I feel like I need to use reduce to count duplicate ages and then filter it based on that but how do I get the values of those ages?
EIDT:
Sorry for not being clear:
This is what I need:
{
23: [
{ name: 'Suzi', hoby: 'golf' },
{ name: 'Joe', hobby: 'books'}
],
15: [
{ name: 'Gary', hobby: 'books' }
] ,
.
.
.
}
You're actually going to want to reduce, not filter. Filtering an Array means to remove elements and place the kept elements into a new container. Reducing an array means to transform it into a single value in a new container. Mapping an array means to transform every value in place to a new container. Since you want to change how the data is represented that's a Reduction, from one form to another more condensed form.
Assume your Array of values is stored in let people = [...]
let peopleByAge = people.reduce(function (accumulator, value, index, array){
// The first time through accumulator is the passed extra Object after this function
// See the MDN for Array.prototype.reduce() for more information
if (accumulator[value.age] == undefined){
accumulator[value.age] = [];
}
accumulator[value.age].push(value);
return accumulator
}, {})
console.log(peopleByAge) // { 23: [{ age: 23, name: ..., hobby: ...}, ...], 13: [...], ...}
You can find the MDN article for Array#reduce() here
Thanks to #RobertMennell who patiently answered me and I voted as answer. But I just wanted to write my version which MDN had a great example of. It is a longer version assuming the people is the array name:
const groupedByvalue = 'age';
const groupedArray = people;
const groupBy = (peopleArray, value) => {
return peopleArray.reduce((acc, obj) => {
const key = obj[value];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
console.log(groupBy(groupedArray,groupedByvalue));
Update:
More polished using ternary operator:
const groupedByvalue = 'age';
const groupedArray = people;
const groupBy = (peopleArray, value) => {
return peopleArray.reduce((acc, obj) => {
const key = obj[value];
(!acc[key]) ? (acc[key] = []) : (acc[key].push(obj))
return acc;
}, {});
}
console.log(groupBy(groupedArray,groupedByvalue));
I'm looking for a way to convert this array of recursive objects into a flat array of objects to make it easier to work with.
[
{
"name": "bill",
"car": "jaguar",
"age": 30,
"profiles": [
{
"name": "stacey",
"car": "lambo",
"age": 23,
"profiles": [
{
"name": "martin",
"car": "lexus",
"age": 34,
"profiles": []
}
]
}
]
}
]
This is the expected output.
[
{
"name": "bill",
"car": "jaguar",
"age": 30,
},{
"name": "stacey",
"car": "lambo",
"age": 23,
},{
"name": "martin",
"car": "lexus",
"age": 34,
}
]
Each profiles array can have n amount of items, which may or may not have an empty array of sub profiles. Note the converted array objects don't contain profiles after the conversion.
I'm open to using underscore or lodash to achieve this.
Let's call your original data o, combining Array.prototype.reduce with recursion I came up with this:
o.reduce(function recur(accumulator, curr) {
var keys = Object.keys(curr);
keys.splice(keys.indexOf('profiles'), 1);
accumulator.push(keys.reduce(function (entry, key) {
entry[key] = curr[key];
return entry;
}, {}));
if (curr.profiles.length) {
return accumulator.concat(curr.profiles.reduce(recur, []));
}
return accumulator;
}, []);
I would use a recursive function and pass the resulting array in it to avoid working with globals, something in the lines of:
var target = [];
var extractElements(source, target) {
//TODO: check if source is array
for (var i=0; i<source.length; i++) {
// create a new element with our data
var newElement = {
name: source[i].name,
car: source[i].car,
age: source[i].age
};
// put it in our flattened array
target.push(newElement);
// check if we need to go deeper and pass our flattened array around
if (source[i].profiles instanceof Array &&
source[i].profiles.length>0)
extractElements(source[i].profiles, target);
}
}
console.log(target) // should list your elements nicely
I haven't tested it, so use it for inspiration but beware :)
(edit1: "var i" in for)
const _ = require('lodash')
const arrayFromObject = (currentObject, currentArray) => {
const {profiles, ...rest} = currentObject
if (!_.isEmpty(currentObject.profiles)) {
return arrayFromObject(currentObject.profiles!, [...currentArray, rest])
}
return [...currentArray, rest]
}
const flatArray = arrayFromObject(myRecursiveObject, [])
Hi this can also be tried...
var out = [];
var i=0;
var extract = function(s, out) {
if(s[0] == null){
i = out.length -1;
return false;
}else {
out.push(s[0]);
}
extract(s[0].profiles, out);
delete out[i--].profiles;
};
extract(a, out); /// here 'a' is the input array and 'out' output
console.log(out);
All the best...
var _ = require('lodash')
/**
* Flatten a array-object via recursive property
* #see {#link http://stackoverflow.com/questions/31829897/convert-recursive-array-object-to-flat-array-object}
* #param {Array} arr Array of objects with recursive props
* #param {String} recursiveProperty The string of the recursive property
* #return {Array} Flat array of all recursive properties without recursive property
*/
function arrExtract (arr, recursiveProperty) {
var extracted = []
function _arrExtract (children) {
_.each(children, function (item) {
if (item[recursiveProperty] && item[recursiveProperty].length) _arrExtract(item[recursiveProperty])
extracted.push(_.omit(item, recursiveProperty))
})
}
_arrExtract(arr)
return extracted
}
module.exports = arrExtract
Almost three years later and still looking for a one-size fits solution for this. Here it is, heavily influenced by #axelduch's answer.
const {isPlainObject, isArray, get, omit, reduce} = require('lodash')
const recursiveFlatten = (tree, headProp, parentIdProp, parentRefProp, parent = {}) => {
tree = isArray(tree) ? tree : [tree]
return reduce(tree, (acq, current) => {
const currentWithoutHead = omit(current, [headProp])
if (parentIdProp && parentRefProp) currentWithoutHead[parentRefProp] = parent[parentIdProp] || null
acq = [...acq, currentWithoutHead]
const next = get(current, headProp)
if (isPlainObject(next) || isArray(next)) {
parent = currentWithoutHead
acq = [...acq, ...recursiveFlatten(next, headProp, parentIdProp, parentRefProp, parent)]
}
return acq
}, [])
}
Here's a simple example:
const example = recursiveFlatten({
name: 'bill',
love: true,
lovers: [{
name: 'jil',
love: false,
lovers: [{
name: 'diana',
love: false,
lovers: false
}, {
name: 'einstein',
love: false,
lovers: {
name: 'carl sagan',
love: false,
lovers: false
}
}]
}]
}, 'lovers')
[ { name: 'bill', love: true },
{ name: 'jil', love: false },
{ name: 'diana', love: false },
{ name: 'einstein', love: false },
{ name: 'carl sagan', love: false } ]
Here's an example adding parentId prop via parentRef.
const example = recursiveFlatten({
name: 'bill',
love: true,
lovers: [{
name: 'jil',
love: false,
lovers: [{
name: 'diana',
love: false,
lovers: false
}, {
name: 'einstein',
love: false,
lovers: {
name: 'carl sagan',
love: false,
lovers: false
}
}]
}]
}, 'lovers', 'name', 'parentName')
[ { name: 'bill', love: true, parentName: null },
{ name: 'jil', love: false, parentName: 'bill' },
{ name: 'diana', love: false, parentName: 'jil' },
{ name: 'einstein', love: false, parentName: 'jil' },
{ name: 'carl sagan', love: false, parentName: 'einstein' } ]
Here's a fairly simple technique that will solve the problem as originally defined.
const recursiveFlatten = (tree) =>
tree .length == 0
? []
: tree .flatMap (({profiles = [], ... rest}) => [{... rest}, ... recursiveFlatten (profiles)])
const tree = [{name: "bill", car: "jaguar", age: 30, profiles: [{name: "stacey", car: "lambo", age: 23, profiles: [{name: "martin", car: "lexus", age: 34, profiles: []}]}]}, {name: "denise", car: "pinto", age: 28}]
console .log (
recursiveFlatten (tree)
)
This hard-codes the name "profiles" and removes it, keeping the rest of the properties intact in the copy generated.
Your own answer suggest substantially more complex requirements. This version handles these through several optional parameters, the way your answer does, although the way it's called changes here and could easily be altered if necessary:
const recursiveFlatten = (headProp, parentIdProp, parentRefProp, parent = {}) => (tree) =>
tree .length == 0
? []
: tree .flatMap (({[headProp]: children = [], ... rest}) => [
{
... rest,
... (parentIdProp && parentRefProp ? {[parentRefProp]: parent[parentIdProp] || null} : {})
},
... recursiveFlatten (headProp, parentIdProp, parentRefProp, rest) (children)
])
const tree = [{name: "bill", car: "jaguar", age: 30, profiles: [{name: "stacey", car: "lambo", age: 23, profiles: [{name: "martin", car: "lexus", age: 34, profiles: []}]}]}, {name: "denise", car: "pinto", age: 28}]
console .log (recursiveFlatten ('profiles') (tree))
console .log (recursiveFlatten ('profiles', 'name', 'parentName') (tree))
I wouldn't be thrilled about this API in my own code-base, though. The differing behaviors depending on how many parameters are passed adds unnecessary complexity. I would probably bury them under an API such as
const recursiveFlatten = (parentIdProp, parentRefProp) => (headProp) => (tree) => ...
Then we could create functions we need, such as using
const flattenProfiles = recursiveFlatten (null, null) ('profiles')
and
const flattenAndExpand = recuriveFlatten ('name', 'parentName') ('profiles')
to replace the two call inside the console .log () statements above.