Reduce returns undefined - javascript

I have an Array of Objects (Cars) :
var car = [
{speed: 20, color: "red"},
{speed: 5, color: "blue"},
{speed: 80, color: "yellow"},
{speed: 79, name: "orange"}
];
and a function that should return the fastest Car in the Array :
function getFastestCar(cars) {
cars.reduce(function (prevFastestCar,curFastestcar) {
if (curFastestcar.speed > prevFastestCar.speed) return curFastestcar;
else return prevFastestCar;
}, {speed: -Infinity, name: "test"});
};
After searching for a few hours I couldn´t find any solution why the function is returning undefined. I debugged the code and the function works perfectly fine, except in the last "step" it somehow replaces the fastest Car with undefined. I´m trying to understand the concept behind the reduce Method I know that there are easier ways to do this, but I´m curious why it is not working correctly.

You need to return the reduced value from the function.
return cars.reduce(..);
See the description of reduce.
Return value
The value that results from the reduction.

This is probably just personal preference, but I don't like using Array.reduce for tasks involving comparison. I think the following is much easier to follow:
const cars = [
{speed: 20, color: "red"},
{speed: 5, color: "blue"},
{speed: 80, color: "yellow"},
{speed: 79, name: "orange"}
];
function getFastestCar(cars) {
var fastestCar = {};
if (cars.length) {
cars.forEach(car => {
fastestCar = fastestCar.speed > car.speed ? fastestCar : car;
});
}
return fastestCar;
}
console.log(getFastestCar(cars));

Related

Basic programming - array of objects to a multi-dimensional object

I've been stuck on this for hours.
I have a list of objects:
const myCompanyList = [
{name: 'coca-cola', size: 'big', color: 'red'},
{name: 'my-cola', size: 'small', color: 'purple'},
{name: 'pepsi', size: 'big', color: 'blue'}
];
I need to get it into this format:
myJson = {
companies: {
big: {
coca-cola: {color: 'red'},
pepsi: {color: 'blue'}
},
small: {
my-cola: {color: 'purple'}
}
}
}
I've tried doing this:
wrapperObject = {};
innerObject = {};
for each object in myCompanyList {
innerObject[object.size] = { object.name : {color: object.color}}
}
but the object[name] bit overwrites. How can I write this so I can dynamically get names on each object/map level? Do I need to make another inner object/map to dynamically write the names?
I've tried writing this in Java but I ended up with 5 dimensional maps and it didn't work, so I just wondered if there was something simple I'm missing - answers in Java, javascript or pseudocode thanks.
You can use Array.reduce() to create a map, Try the following :
let myCompanyList = [{name: "coca-cola", size: "big", color: "red"}, {name: "my-cola", size: "small", color: "purple"},{name: "pepsi", size: "big", color:"blue"}];
let result = {};
result.companies = myCompanyList.reduce((a,curr)=>{
a[curr.size] = a[curr.size] || {};
a[curr.size][curr.name] = {"color" : curr.color};
return a;
},{});
console.log(result);

How to locate an object within an array and replace it with a new object? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have an array like so:
[
{color: "blue"},
{color: "red", size: "large"},
{color: "green", size: "medium"}
]
Showing this how can I:
Find the object with a color of green
Replace that object with {color: "green", size: "x-large"}
You can use the function find and then modify the found object.
var array = [{color: "blue"}, {color: "red", size: "large"}, {color: "green", size: "medium"}],
found = array.find(({color}) => color === 'green');
if (found) found.size = 'x-large';
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use map array it will return array.
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
const arr= [
{color: "blue"},
{color: "red", size: "large"},
{color: "green", size: "medium"}
];
let result = arr.map(obj=>{
return obj.color=='green'? {color: "green", size: "x-large"}:obj;
})
console.log(result)
you can also use find
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
DEMO
const arr = [{
color: "blue"
}, {
color: "red",
size: "large"
}, {
color: "green",
size: "medium"
}];
let result = arr.find(v => v.color == 'green');
if (result) {
result.size = 'x-large';
}
console.log(arr)
If need to replace in the existing object you can use forEach and check for the color, else if need to return a new array you can use map function
var oldObj = [{
color: "blue"
},
{
color: "red",
size: "large"
},
{
color: "green",
size: "medium"
}
]
oldObj.forEach(function(item) {
if (item.color === 'green') {
item.size = 'x-medium';
}
});
console.log(oldObj)

Trying to recreate my console.log objects

I have a var that contains 4 objects that I see when I log it out in the console. But I have been trying to create the structure of this return variable (I want to sort it but first want to recreate the structure), but are failing at the last hurdle.
This is what the console puts out on original variable: [Object, Object, Object, Object]
This is what I get with created variable: [Object]
Here is my code to try and re-create it:
this.obj = [{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'blue'}],
[{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'green'}],
[{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'red'}],
[{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'yellow'}]
;
The first objects of both original and created are identical, but why does it not see my other three objects? If I add two [] around my code, it's sees all four, but then they have changed to arrays instead of objects...
Your code seems broken, if you order it in a readable way then it's clear:
var obj = [
{
items: [{
code: 'bravo', color: 'blue', date: '2017-01-01', pos: 'up'
}, {
code: 'alpha', color: 'blue', date: '2017-01-02', pos: 'down'
}],
color: 'blue'
}] // <=== the array ends here, but now you have this:
, [{ items: [{ ...
The compiler then does this:
var obj = [
{
items: [{
code: 'bravo', color: 'blue', date: '2017-01-01', pos: 'up'
}, {
code: 'alpha', color: 'blue', date: '2017-01-02', pos: 'down'
}],
color: 'blue'
}
], _a = (void 0)[0], _b = ....
As you can see it creates another variable (_a) to store the other data.
Got it working for anyone who wants to know:
this.obj = [{0:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'blue'}},
{1:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'green'}},
{2:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'red'}},
{3:{items:[{code:'bravo',color:'blue',date:'2017-01-01',pos:'up'},
{code:'alpha',color:'blue',date:'2017-01-02',pos:'down'}],
color:'yellow'}}]
;
}

How to count items in List with ImmutableJS?

I have a List which looks like this:
["green", "blue","green","green", "blue", "black"]
How can I use the ImmutableJS operators to count these items and get a Map which could look like this:
{ green: {name: green, count: 3}, blue:{name: blue, count: 2}, black:{name: black, count: 1}}
I found the following function here to do just that in plain JS, so how could I achieve this with ImmutableJS?
export const countOccurances = obj => {
return obj
.reduce((counter, x) => {
if (counter.hasOwnProperty(x)) {
counter[x].count = counter[x].count + 1
} else {
counter[x] = {name: x, count: 1}
}
return counter;
}, {})
}
Try groupBy followed by map. Something like this:
list.groupBy(elem => elem).map(arr => {
return {"name" : arr.get(0), "count": arr.size }
})
list.groupBy(elem => elem) will return a KeyedSeq with the color String as it's key and an Iterable of Strings as value. It would look like this in pure JS.
{ green: ["green","green","green"], blue:["blue","blue"], black: ["black"]}
We can then map these to return the size of the iterable as well as the name and we should get what you wanted:
{ green: {name: "green", count: 3}, blue:{name: "blue", count: 2}, black:{name: "black", count: 1}}
Of course if you wanted to get exactly that, you would need to use toJS() at the end.
You could also use a mixed solution:
list.toJS().length

Code in "Don't Be Scared of Functional Programming"

I've been reading through an article titled Don’t Be Scared Of Functional Programming and there is a piece of code I'm having trouble understanding (pasted below). The code's purpose is to get an item from an array of objects called data. What I don't understand is how the function within the function works. Where is the item argument coming from when you invoke getItem()?
var data = [
{
name: "Jamestown",
population: 2047,
temperatures: [-34, 67, 101, 87]
},
{
name: "Awesome Town",
population: 3568,
temperatures: [-3, 4, 9, 12]
}
{
name: "Funky Town",
population: 1000000,
temperatures: [75, 75, 75, 75, 75]
}
];
function getItem(propertyName) {
// Return a function that retrieves that item, but don't execute the function.
// We'll leave that up to the method that is taking action on items in our
// array.
return function(item) {
return item[propertyName];
}
}
I Understand that JS allows functions to be passed as arguments because they are treated as “first-class objects" in JS, but I don't understand where that item argument would be coming from.
This is defining a function that will accept a parameter called item which can be used to return the propertyName element from the given item. It is the function that is then passed back to the caller of getItem. It would be used as follows:
var getName = getItem('name');
var result = getName(x);
Where x is a variable containing a property called 'name'
Maybe this helps a bit.
It utilized a partial application of the first parameter propertyName with Function.prototype.bind():
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
Small example with your data and function:
function getItem(propertyName, item) {
return item[propertyName];
}
var data = [{ name: "Jamestown", population: 2047, temperatures: [-34, 67, 101, 87] }, { name: "Awesome Town", population: 3568, temperatures: [-3, 4, 9, 12] }, { name: "Funky Town", population: 1000000, temperatures: [75, 75, 75, 75, 75] }],
// this returns a function with only item as parameter
getName = getItem.bind(null, 'name');
document.write('<pre>' + JSON.stringify(data.map(getName), 0, 4) + '</pre>');

Categories