Unable to use array on reduce - javascript

Const people = [ { name: 'siddiq', age: 20} , { name: 'anas', age: 19}]
Const arr = people.reduce((acc, curr) => acc.push(curr.age), [])
It is not working. What i want is to creare an array with only ages...??

You should use map() instead:
const people = [ { name: 'siddiq', age: 20} , { name: 'anas', age: 19}]
const arr = people.map(p => p.age)
//[20, 19]

reduce() requires that you return the accumulator from the callback function (since the accumulator might not be a mutable object). push() returns the length of the updated array, so the second iteration tries to do (1).push(curr.age, []), which doesn't work.
The comma operator is useful for this in arrow functions.
Also, there's no reason to push [] onto acc.
const people = [ { name: 'siddiq', age: 20} , { name: 'anas', age: 19}]
const arr = people.reduce((acc, curr) => (acc.push(curr.age), acc), []);
console.log(arr);

Another option is to use the spread syntax to ensure you'll return an array within reduce method in a cleaner and modern way.
const people = [ { name: 'siddiq', age: 20} , { name: 'anas', age: 19}]
const arr = people.reduce((acc, curr) => [...acc, curr.age], []);
console.log(arr);

Related

How do I convert an array of objects into an object (dynamically) in JavaScript [duplicate]

This question already has answers here:
Convert array of objects with same property to one object with array values
(6 answers)
Closed 2 months ago.
I have an array of objects that looks like this:
arr = [
{name: "john", age: 23},
{name: "mary", age: 40},
{name: "zack", age: 17}
]
I am trying to convert it into something like this:
{
name: ["john", "mary", "zack"],
age: ['23', 40, 17]
}
i have tried the following
arr.map(item => item.name)
arr.map(item => item.age)
return {names, ages}
and it works fine but this assumes that you already know, beforehand, the keys of the objects you're converting.
I want to be able to load the object keys and corresponding array of values dynamically. Assuming i don't know that the objects in our example array have "name" and "age" as keys.
You could reduce the array and the entries of the object and collect the values in the group of the keys.
const
data = [{ name: "john", age: 23 }, { name: "mary", age: 40 }, { name: "zack", age: 17 }],
result = data.reduce((r, o) => Object.entries(o).reduce((t, [k, v]) => {
if (!t[k]) t[k] = [];
t[k].push(v);
return t;
}, r), {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could get the key of the first element and then map through it. With each, get its corresponded values
const arr = [
{ name: "john", age: 23, gender: "male" },
{ name: "mary", age: 40, gender: "female" },
{ name: "zack", age: 17, gender: "male" },
]
const res = Object.keys(arr[0]).reduce((acc, el) => {
const values = arr.map((item) => item[el])
return { ...acc, [el]: values }
}, {})
console.log(res)
Assuming that each object in your list has the same keys you could get the keys of the first object
const keys = Object.keys(arr[0])
and then map through the keys with your above approach
const returnObj = {}
keys.forEach(key => {
returnObj[key] = arr.map(item => item[key])
})
return returnObj
You can use Object.entries for the mapping.
var arr = [
{name: "john", age: 23},
{name: "mary", age: 40},
{name: "zack", age: 17}
];
var entries = arr.map((item) => Object.entries(item));
var result = {};
entries.forEach(entry => {
entry.forEach(item => {
if (result[item[0]] && result[item[0]].length > 0) {
result[item[0]].push(item[1]);
} else {
result[item[0]] = [item[1]];
}
});
});
console.log(result);
You can make use of Array.reduce and Object.keys.
let arr = [
{name: "john", age: 23},
{name: "mary", age: 40},
{name: "zack", age: 17}
]
const formatData = (data) => {
return data.reduce((res, obj) => {
Object.keys(obj).map(d => {
res[d] = [...(res[d] ||[]), obj[d]]
})
return res;
}, {})
}
console.log(formatData(arr))
You can do this with Ramda
import { mergeWith, concat } from “Ramda”
const mergeConcat = mergeWith(concat)
mergeConcat(arr)

How to get a particular attribute from an array of array objects?

I have an Array of Arrays, and each Array consists of objects. Here is a simplified version of what I'm referring to (it is a console.log of my original array) -
Array - [Array(2), Array(3), Array(2)]
Each Array has objects in the following format (taking the first array from above) -
Array(2) -
0: {name: "test", score:40, date: "2018-09-18T00:00:00.000Z"}
1: {name: "test2", score:50 date: "2018-09-18T00:00:00.000Z"}
The other arrays are similar with the same attributes and different values.
I am trying to fetch the name attribute from each of these objects. I tried the below code - but I end up getting an undefined value:
const test1= array1.map(x=> x.values) // this gives me the array of arrays
const test2 = test1.map(function(y){return y.name})// this is my attempt to get the 'name' attribute from all of the arrays that include the objects.
What am I missing out on here? Is there a better way to get the attribute using arrow functions?
Flatten it, and map it to names or Vise versa
First flatten it, and map
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = [].concat(...array).map(({name})=>name);
console.log(res);
Now, map it to names and then flatten
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = [].concat(...array.map(a=>a.map(b=>b.name)))
console.log(res);
Now, In this one, certainly you can notice that we are actually mapping it in each level (we have to, no other way with first map only approach. so we can perform a reduce in place of the outer map and concat it there itself, so we can avoid the outer concat (for flatten) and inner concat will actually flatten it. Here we go:
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = array.reduce((r, a)=>r.concat(a.map(b=>b.name)), []);
console.log(res);
/* TEST DATA */
array1 = [
{ name: 'test1', score: 40, date: '2018-09-18T00:00:00.000Z' },
];
array2 = [
{ name: 'test4', score: 50, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test5', score: 40, date: '2018-09-18T00:00:00.000Z' },
];
array3 = [
{ name: 'test6', score: 50, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test7', score: 50, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test8', score: 40, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test9', score: 50, date: '2018-09-18T00:00:00.000Z' },
];
testResults = [array1, array2, array3];
// Solution
function getListOfName(){
let names = [];
testResults.map(testResult => {
testResult.map(({name}) => {if(name) names.push(name)})
})
return names;
}
console.log("Full list of names", getListOfName());
// If you want to restrict to K names from each array
function getFirstKNamesfromArray(limit){
let names = [];
testResults.map(testResult => {
testResult.map(({name}, index) => {
if(name && (index < limit)) names.push(name)
})
})
return names
}
console.log("First 2 names from each array", getFirstKNamesfromArray(2));
Take into account that map returns an array; you iterate over it. Filter or reduce do the same.
const test1= array1.map(x=> x.values) // x doesn't have a property named "value"
//simply use forEach
array1.forEach((el) => console.log(el.name))
If you want to capture the names inside a collection:
const let container = [];
array1.forEach((el) => container.push(el.name))
A good way to better understand this iterator functions would be to first use loops and then attempt to "translate" your code into one of them.
Because in your first map x is an array, not an object. So, there is no value. You should map inner arrays then get the desired value.
const arr = [
[
{
name: "test",
score: 40,
date: "2018-09-18T00:00:00.000Z"
},
{ name: "test2", score: 50, date: "2018-09-18T00:00:00.000Z" }
],
[
{
name: "foo",
score: 40,
date: "2018-09-18T00:00:00.000Z"
},
{ name: "bar", score: 50, date: "2018-09-18T00:00:00.000Z" }
]
];
const test1 = arr
.map(x => x.map(y => y.name))
.reduce((acc, el) => [...acc, ...el], []);
console.log(test1);
This should work fine. You need to flatten the array structure and map the names.
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
const names = array.reduce((acc, innerArray) => {
return [...acc, ...innerArray.map(entry => entry.name)]
}, [])
console.log(names)
Here:
const arr = [
[{name: 'a', date:'x'}, {name: 'b', date:'y'}],
[{name: 'c', date:'x'}, {name: 'd', date:'y'}]
];
const names = arr.map(el => el.map(obj => obj.name));
console.log(names.join());
console.log(names.flat());
you can use flat() to keep names in an array or join() to merge the names into a string.
const test1= array1.map(x=> x.values)
This is returning undefined.
let requiredArr = [];
let array1 = [Array(2), Array(3), Array(2)]
let test2 = array1.map(x => x.map(y => requiredArr(y.name));
test2 will give the desired result.
Adding to Koushik's example, with ES2019, you can use flat() to flatten nested arrays:
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = array.flat().map( ({name}) => name );
console.log(res);
Or if you have deeper levels:
const array = [[[{name: 'test1'}], {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = array.flat(2).map( ({name}) => name );
console.log(res);
And so on.

Loop through an object of objects and extract key value that equals something specific?

I am trying to avoid dependencies such as loaddash (_.filter) and use pure javascript.
Basically I have an object of objects, and I need to loop through and filter out all that dont have a parent_id of a specific value.
var filterBy = 50
var obj = {
256: {
name: john
parent_id: 50
},
341: {
name: dwit
parent_id: 50
},
398: {
name: ryan
parent_id: 30
},
421: {
name: jack
parent_id: 50
}
}
with the result being
var filteredOBJ = {
256: {
name: john
parent_id: 50
},
343: {
name: dwit
parent_id: 50
},
421: {
name: jack
parent_id: 50
}
}
const result = {};
for(const [key, val] of Object.entries(obj)) {
if(val.parent_id === filterBy) {
result[key] = val;
}
}
Just turn what you described into code and you're done.
If you like the loadash approach, but want to use javascript, reduce() on the Object.entries() will give you nice functional approach, although the above forEach solutions probably win for readabilty.
var filterBy = 50
var obj = {256: {name: 'john',parent_id: 50},341: {name: 'dwit',parent_id: 50},398: {name: 'ryan',parent_id: 30},421: {name: 'jack',parent_id: 50}}
let r = Object.entries(obj).reduce((a, [k, v]) =>
v.parent_id === filterBy
? Object.assign(a, {[k]: v})
: a, {})
console.log(r)
Here's an implementation of a simple filter in ES6 :
let myObj = {
256: {
name: "john",
parent_id: 50
},
341: {
name: "dwit",
parent_id: 50
},
398: {
name: "ryan",
parent_id: 30
},
421: {
name: "jack",
parent_id: 50
}
}
let result = {};
Object.entries(myObj).forEach( ([key, value]) => {
if(key != 398) // condition over keys
result[key] = value;
})
console.log(result);
There is a counterpart Object.fromEntries() to Object.entries() so you can use vanilla javascript Array.prototype.filter(). Just convert object to entries, filter and convert back from entries to object.
const filterBy = 50
const obj = {256: {name: 'john',parent_id: 50}, 341: {name: 'dwit',parent_id: 50}, 398: {name: 'ryan',parent_id: 30}, 421: {name: 'jack',parent_id: 50}}
const filteredObj = Object.fromEntries(
Object.entries(obj).filter(
([key, value]) =>
value.parent_id === filterBy
)
)
console.log(filteredObj)

Creating a key:value object from a flat object

I'm using Javascript to get data from an API.
I get the following list of objects.
[
{name: 'Cat', value: 2, extra: 'data'},
{name: 'Dog', value: 3, extra: 'data'}
]
I'm trying to get to the following form
[
cat: {value: 2},
dog: {value: 3}
]
I'm currently trying using map but I don't see where the key part comes in.
return data.map((item) => ({
value: item.value
}));
var data = [
{name: 'Cat', value1: 2, value2: 3},
{name: 'Dog', value1: 3, value2: 4}
]
var result = data.map((item) => {
var name = item.name
delete item.name
//if you want to modify some property
item.value1 = item.value1 + "$"
return {[name]: {...item}}
})
console.log(result)
const result = {};
for(const {name, value} of array)
result[name] = { value };
A plain old for loop does it. With functional programming you would have to use reduce to boil it down to one single object, map always returns an array.
const result = array.reduce((res, {name, value}) => ({ ...res, [name]: {value}}), {});
You can use Object.assign() with map() method to return object as a result.
const data = [{name: 'Cat', value: 2},{name: 'Dog', value: 3}]
const result = Object.assign({}, ...data.map(({name, value}) => ({[name]: {value}})))
console.log(result)

Using template literal for dynamic property in ReactJS

My failed attempt:
temp.map((obj,i) => ({
obj[`person${++i}`] = obj.person.name
})
I want to produce something like this
[{id:324, person1:'mike'},{id:23, person2:'jane'}]
But I'm stuck on making the property dynamic with concatenation using template literal string.
Issue with you code is, you are directly returning the data by using
() => ({....})
and there you are using obj[...] that is not a valid key.
map return the a new array so store the result in a new variable, if you want to modify the same array then better to use forEach.
Check this snippet:
let arr = [{id: 10, name: 'A'}, {id: 20, name: 'B'}];
let newArr = arr.map((el,i) => ({
id: el.id,
[`name${i+1}`]: el.name
}));
console.log('new array', newArr);
Modifying the same data using forEach:
let arr = [{id: 10, name: 'A'}, {id: 20, name: 'B'}];
arr.forEach((el,i) => {
el[`person${i+1}`] = el.name;
})
console.log('modified array', arr);
This should do it:
var myInput = ["John", "Jane", "Steven", "Alice"];
var myOutput = myInput.map ((name, index) => {
var out = {};
out[`person${index}`] = name;
return out;
}); // myOutput is [{person1:"John"}, {person2:"Jane"} ... etc.
map creates a new array rather than modifying the existing one. The values of the array are made out of the return values of the function, so if you want your values to be objects, you must create new objects and then assign your properties to them.
How about this?
describe("sample test", () => {
it("Dynamic property in ES6", () => {
const temp = [
{ id: 324, person: { name: "mike" } },
{ id: 23, person: { name: "jane" } }
];
console.log(
temp.map((obj, i) => ({
id: obj.id,
[`person${i + 1}`]: obj.person.name
}))
);
});
});
Output:
[ { id: 324, person1: 'mike' }, { id: 23, person2: 'jane' } ]

Categories

Resources