Reduce array of objects on key and sum value into array - arrays

I have the following object:
data = [
{ name: 'foo', type: 'fizz', val: 9 },
{ name: 'foo', type: 'buzz', val: 3 },
{ name: 'bar', type: 'fizz', val: 4 },
{ name: 'bar', type: 'buzz', val: 7 },
];
And used lodash map:
result = _.map(data, function item, idx){
return {
key: item[key],
values: item.value,
}
}
Which results in:
[
{ key: foo, val: 9 },
{ key: foo, val: 3 },
{ key: bar, val: 4 },
{ key: bar, val: 7 },
]
but now I'm trying to return:
[
{ key: 'foo', val: 12 },
{ key: 'bar', val: 11 },
]
I tried using reduce which seems to only output to a single object, which I could then convert back into an array, but I feel like there must be an elegant way to use lodash to go from my source data straight to my desired result without all of the intermediate steps.
I thought this was addressing my exact problem, but it seems like quite a bit of work just to have to convert the object into the desired array of objects outlined above.
Cheers.

A twist to the accepted answer that uses groupBy instead of reduce to do the initial grouping:
var result = _.chain(data)
.groupBy('name')
.map((group, key) => ({ key, val : _.sumBy(group, 'val') }))
.value();

Interestingly not straight forward, because of wanting to accumulate the value by key, but then wanting the key as a value of the property key. So somewhat like an inverse map reduce:
var result =
_.chain(data)
.reduce(function(memo, obj) {
if(typeof memo[obj.name] === 'undefined') {
memo[obj.name] = 0;
}
memo[obj.name] += obj.val;
return memo;
}, {})
.map(function (val, key) {
return {key: key, val: val};
})
.value();
For the sake of brevity in es6:
_.chain(data)
.reduce((memo, obj) => {
memo[obj.name = obj.val] += obj.val;
return memo;
}, {})
.map((val, key) => ({key, val}))
.value();

You can get all the unique names using map() and uniq(), and then map() each name to get their respective sums using sumBy().
var result = _(data)
.map('name')
.uniq()
.map(key => ({
key,
val: _(data).filter({ name: key }).sumBy('val')
}))
.value();
var data = [
{ name: 'foo', type: 'fizz', val: 9 },
{ name: 'foo', type: 'buzz', val: 3 },
{ name: 'bar', type: 'fizz', val: 4 },
{ name: 'bar', type: 'buzz', val: 7 }
];
var result = _(data)
.map('name')
.uniq()
.map(key => ({
key,
val: _(data).filter({ name: key }).sumBy('val')
}))
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
Here is a non es6 version:
var result = _(data)
.map('name')
.uniq()
.map(function(key) {
return {
key: key,
val: _(data).filter({ name: key }).sumBy('val')
};
})
.value();

Here's a simple non-lodash version.
const data = [{
name: 'foo',
type: 'fizz',
val: 9
},
{
name: 'foo',
type: 'buzz',
val: 3
},
{
name: 'bar',
type: 'fizz',
val: 4
},
{
name: 'bar',
type: 'buzz',
val: 7
},
]
const result = data.reduce((acc, curr) => {
const index = acc.findIndex(item => item.name === curr.name)
index > -1 ? acc[index].val += curr.val : acc.push({
name: curr.name,
val: curr.val
})
return acc
}, [])
console.log(result)

Related

How to Change Data in React

I want to create data from DATA to OPTIONS.
const DATA = [
{ name: 'aaa', id: 'happy' },
{ name: 'bbb', id: 'time' },
{ name: 'ccc', id: 'party' },
];
const OPTIONS =[{value:'aaa', label:'aaa'},
{value:'bbb', label:'bbb'},
{value:'ccc', label:'ccc'},
]
I need only name value in DATA.
so, using name value, I want to create OPTIONS.
Fuction Test(){
const DATA = [
{ name: 'aaa', id: 'happy' },
{ name: 'bbb', id: 'time' },
{ name: 'ccc', id: 'party' },
];
const OPTIONS =[{value:'aaa', label:'aaa'},
{value:'bbb', label:'bbb'},
{value:'ccc', label:'ccc'},
]
}
let newObject=[];
const createData = () => {
const arr = selectMainId.data.map(data => data.name);
arr.map(data => newObject.push({ value: data, label: data }));
console.log('newObj:', newObject);
};
console.log('newObj1:', newObject))
this case, I can get OPTIONS same data.
so, I can get newObject in createData console.
but I can't get newObject in Test console.
I don't know this issue.
Do you know effective way?
please help me.
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
Clean and simplest way:
const DATA = [
{ name: 'aaa', id: 'happy' },
{ name: 'bbb', id: 'time' },
{ name: 'ccc', id: 'party' },
];
const OPTIONS = DATA.map(x => ({value: x.name, label: x.name }));
console.log(OPTIONS);
You just need to do
const createData = (data) => {
return data.map(d => ({name: data.name, label: data.name}))
};
const option = createData(data)

Filter an array of object with another array - returning two values

I wanted to filter my seach by name and type when a user types on the search box however I am just getting back the names but not by type.
This is my array:
const projects = [
{
id: 1,
name: 'protfolio',
type: ['react']
},
{
id: 2,
name: 'RoboFriends',
type: ['react']
},
{
id: 3,
name: 'Background-gradient',
type: ['html ', 'css ', 'javaScript']
},
{
id: 4,
name: 'Election-map',
type: ['html ', 'css ', 'javaScript']
},
{
id: 5,
name: 'To-Do-List',
type: ['react']
}
]
The function I've reacted to filter over my array and return the project name and also type
const projectFilter = this.state.projects.filter( project => {
return project.name.toLowerCase().includes(this.state.searchField.toLowerCase())
|| project.type.includes(this.state.searchField);
})
Your code is fine. I checked. Make sure your searchField came as you wish.
Check this out
function myFunction() {
const projects = [
{
id: 1,
name: 'protfolio',
type: ['react']
},
{
id: 2,
name: 'RoboFriends',
type: ['react']
},
{
id: 3,
name: 'Background-gradient',
type: ['html ', 'css ', 'javaScript']
},
{
id: 4,
name: 'Election-map',
type: ['html ', 'css ', 'javaScript']
},
{
id: 5,
name: 'To-Do-List',
type: ['react']
}
]
const projectFilter = projects.filter( project => {
return project.name.toLowerCase().includes('react')
|| project.type.includes('react');
})
document.getElementById("test").innerText = (projectFilter[2].name);
}

How can I change TS object array format?

Array which I want change
I have got this array in TypeScript, I want it change as bellow.
list = [{id : 1, name : bus, active : 1}, {id : 2, name : car}]
Can anyone help me?
You can map the input and reduce each element to an object.
const list = [
[{ id: 1 }, { name: 'bus' }, { active: 1 }],
[{ id: 2 }, { name: 'car' }],
];
const result = list.map((el) => {
return el.reduce((acc, curr) => {
return { ...acc, ...curr };
}, {});
});
console.log(result);

how do i filter a array of objects to display only ids of the ones that have all existing type properties

im getting data from an API that looks like this:
const flags = [
{
type: "manyCards",
id: 1
},
{
type: "manyCards",
id: 2
},
{
type: ":premiumCard",
id: 1
},
]
i want to filter/sort it so it displays only the ids that have all types eg. id:1 has both manyCards and premiumCard.
som my result would be result = [1] in this case.
Cant figure out what Array prototypes to use.
To do this, I would group the initial data by id, so that we can know how many types each id has.
Once this is done, we can filter with any conditions we want.
const flags = [
{
type: "manyCards",
id: 1
},
{
type: "manyCards",
id: 2
},
{
type: ":premiumCard",
id: 1
},
{
type: "manyCards",
id: 3
},
{
type: "manyCards",
id: 2
},
{
type: ":premiumCard",
id: 3
},
]
let grouped = flags.reduce(function (r, a) {
r[a.id] = r[a.id] || []
r[a.id].push(a.type)
return r
}, {})
let result = Object.keys(grouped).filter(elem => (grouped[elem].includes("manyCards") && grouped[elem].includes(":premiumCard")))
console.log(result)

Array to array of objects

I have an array of country such as:
country=["Afganistan","Albania","Algeria"]
How can I convert this array into array of objects such as:
newarray=[
{ key: 'Afghanistan', value: 'Afghanistan', text: 'Afghanistan' },
{ key: 'Albania', value: 'Albania', text: 'Albania' },
{ key: 'Algeria', value: 'Algeria', text: 'Algeria' }
]
country=["Afganistan","Albania","Algeria"]
let newarray = [];
country.forEach(item => {
newarray.push({
key: item,
value: item,
text: item
});
});
console.log(newarray);
I found the answer. The method will be:-
let newarray = [];
country.map(item => {
return newarray.push({ key: item, value: item, text: item })
})

Resources