Trouble creating array of objects - javascript

I have an array and I want to pick 3 of its elements and put store it in another array as a single object and again repeatedly follow the same process on every 3 elements of the array. This is my code below:
let breakpoints = [
{name: "from-amonut", value: "100"},
{name: "to-amonut", value: "200"},
{name: "gst", value: "10"},
{name: "from-amonut", value: "200"},
{name: "to-amonut", value: "300"},
{name: "gst", value: "20"},
{name: "from-amonut", value: "300"},
{name: "to-amonut", value: "400"},
{name: "gst", value: "30"}
];
let temp = {
"from_amount": 0,
"to_amount": 0,
"gst": 0
};
let formattedBreakpoints = [];
breakpoints.map((v, k) => {
(v.name == "from-amonut") ? temp.from_amount = v.value: "";
(v.name == "to-amonut") ? temp.to_amount = v.value: "";
(v.name == "gst") ? temp.gst = v.value: "";
((k + 1) % 3 === 0) ? (formattedBreakpoints.push(temp), console.log(temp)) : "";
});
console.log(formattedBreakpoints);
I'm expecting formattedBreakpoints to be [{"from_amount":100, "to_amount":200, "gst":10}, {"from_amount":200, "to_amount":300, "gst":20}.....] but only returns all the objects with the value of last array elements.

You can use Array.reduce() to add all properties to the last object. Whenever the index (i) remainder from 3 is 0, you add another object to the accumulator.
const breakpoints = [{"name":"from-amonut","value":"100"},{"name":"to-amonut","value":"200"},{"name":"gst","value":"10"},{"name":"from-amonut","value":"200"},{"name":"to-amonut","value":"300"},{"name":"gst","value":"20"},{"name":"from-amonut","value":"300"},{"name":"to-amonut","value":"400"},{"name":"gst","value":"30"}];
const result = breakpoints.reduce((r, { name, value }, i) => {
if(i % 3 === 0) r.push({});
const key = name.replace(/-/g, '_');
r[r.length - 1][key] = value;
return r;
}, []);
console.log(result);
What's the problem in your code is the reuse of temp. Since temp is an object, pushing it to the array, adds the reference to the array, and doesn't create a new object. To prevent that, you can init temp whenever you get to the last property. You should also use Array.forEach() (do something with value) instead of Array.map() (create new array with items based on original values).
const breakpoints = [{"name":"from-amonut","value":"100"},{"name":"to-amonut","value":"200"},{"name":"gst","value":"10"},{"name":"from-amonut","value":"200"},{"name":"to-amonut","value":"300"},{"name":"gst","value":"20"},{"name":"from-amonut","value":"300"},{"name":"to-amonut","value":"400"},{"name":"gst","value":"30"}];
let temp = {};
const formattedBreakpoints = [];
breakpoints.forEach((v, k) => {
if(v.name == "from-amonut") temp.from_amount = v.value;
if(v.name == "to-amonut") temp.to_amount = v.value;
if(v.name == "gst") { // whenever we get to gst, we can push to array, and reset temp
temp.gst = v.value;
formattedBreakpoints.push(temp);
temp = {};
};
});
console.log(formattedBreakpoints);

The problem with your code that you are mutating a single object temp and pushing it 3 times to the result array. So what's going on:
You are creating an object
In a map method you are mutating it repeatedly and after every 3 iterations you are setting reference to this object to the result array.
Key word here is reference. That means that this is the same object. For example:
const result = [];
const obj = {};
obj.a = 'a';
result.push(obj); // => result = [{ a: 'a' }]
obj.b = 'b';
result.push(obj); // => result = [{ a: 'a', b: 'b' }, { a: 'a', b: 'b' }]
Try this way:
let formattedBreakpoints = [];
for (let i = 0; i < breakpoints.length; i += 3) {
const breakPointOptions = breakpoints.slice(i, i + 3);
formattedBreakpoints.push(breakPointOptions.reduce((result, { name, value }) => {
result[name] = value;
return result;
}, {}));
}

let breakpoints = [
{name: "from-amonut", value: "100"},
{name: "to-amonut", value: "200"},
{name: "gst", value: "10"},
{name: "from-amonut", value: "200"},
{name: "to-amonut", value: "300"},
{name: "gst", value: "20"},
{name: "from-amonut", value: "300"},
{name: "to-amonut", value: "400"},
{name: "gst", value: "30"}
]
let temp = {
"from_amount" : 0,
"to_amount" : 0,
"gst" : 0
};
let formattedBreakpoints = [];
breakpoints.map((v, k)=>{
(v.name == "from-amonut") ? temp.from_amount = v.value : "";
(v.name == "to-amonut") ? temp.to_amount = v.value : "";
(v.name == "gst") ? temp.gst = v.value : "";
((k + 1) % 3 === 0) ? (formattedBreakpoints.push(temp), temp = {... temp}) : "" ;
});
console.log(formattedBreakpoints);
As temp is an object you are using it by reference. So you need to create a new object each time you push or else the same object will be referenced. Hence I'm using temp itself to create this new object.

Related

Create object from multiple object with same value in map JS [duplicate]

I have an array of objects:
[
{ key : '11', value : '1100', $$hashKey : '00X' },
{ key : '22', value : '2200', $$hashKey : '018' }
];
How do I convert it into the following by JavaScript?
{
"11": "1100",
"22": "2200"
}
Tiny ES6 solution can look like:
var arr = [{key:"11", value:"1100"},{key:"22", value:"2200"}];
var object = arr.reduce(
(obj, item) => Object.assign(obj, { [item.key]: item.value }), {});
console.log(object)
Also, if you use object spread, than it can look like:
var object = arr.reduce((obj, item) => ({...obj, [item.key]: item.value}) ,{});
One more solution that is 99% faster is(tested on jsperf):
var object = arr.reduce((obj, item) => (obj[item.key] = item.value, obj) ,{});
Here we benefit from comma operator, it evaluates all expression before comma and returns a last one(after last comma). So we don't copy obj each time, rather assigning new property to it.
This should do it:
var array = [
{ key: 'k1', value: 'v1' },
{ key: 'k2', value: 'v2' },
{ key: 'k3', value: 'v3' }
];
var mapped = array.map(item => ({ [item.key]: item.value }) );
var newObj = Object.assign({}, ...mapped );
console.log(newObj );
One-liner:
var newObj = Object.assign({}, ...(array.map(item => ({ [item.key]: item.value }) )));
You're probably looking for something like this:
// original
var arr = [
{key : '11', value : '1100', $$hashKey : '00X' },
{key : '22', value : '2200', $$hashKey : '018' }
];
//convert
var result = {};
for (var i = 0; i < arr.length; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result);
I like the functional approach to achieve this task:
var arr = [{ key:"11", value:"1100" }, { key:"22", value:"2200" }];
var result = arr.reduce(function(obj,item){
obj[item.key] = item.value;
return obj;
}, {});
Note: Last {} is the initial obj value for reduce function, if you won't provide the initial value the first arr element will be used (which is probably undesirable).
https://jsfiddle.net/GreQ/2xa078da/
Using Object.fromEntries:
const array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
const obj = Object.fromEntries(array.map(item => [item.key, item.value]));
console.log(obj);
A clean way to do this using modern JavaScript is as follows:
const array = [
{ name: "something", value: "something" },
{ name: "somethingElse", value: "something else" },
];
const newObject = Object.assign({}, ...array.map(item => ({ [item.name]: item.value })));
// >> { something: "something", somethingElse: "something else" }
you can merge array of objects in to one object in one line:
const obj = Object.assign({}, ...array);
Use lodash!
const obj = _.keyBy(arrayOfObjects, 'keyName')
Update: The world kept turning. Use a functional approach instead.
Previous answer
Here you go:
var arr = [{ key: "11", value: "1100" }, { key: "22", value: "2200" }];
var result = {};
for (var i=0, len=arr.length; i < len; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result); // {11: "1000", 22: "2200"}
Simple way using reduce
// Input :
const data = [{key: 'value'}, {otherKey: 'otherValue'}];
data.reduce((prev, curr) => ({...prev, ...curr}) , {});
// Output
{key: 'value', otherKey: 'otherValue'}
More simple Using Object.assign
Object.assign({}, ...array);
Using Underscore.js:
var myArray = [
Object { key="11", value="1100", $$hashKey="00X"},
Object { key="22", value="2200", $$hashKey="018"}
];
var myObj = _.object(_.pluck(myArray, 'key'), _.pluck(myArray, 'value'));
Nearby 2022, I like this approach specially when the array of objects are dynamic which also suggested based on #AdarshMadrecha's test case scenario,
const array = [
{ key : '11', value : '1100', $$hashKey : '00X' },
{ key : '22', value : '2200', $$hashKey : '018' }];
let obj = {};
array.forEach( v => { obj[v.key] = v.value }) //assign to new object
console.log(obj) //{11: '1100', 22: '2200'}
let array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
let arr = {};
arr = array.map((event) => ({ ...arr, [event.key]: event.value }));
console.log(arr);
Was did yesterday
// Convert the task data or array to the object for use in the above form
const {clientData} = taskData.reduce((obj, item) => {
// Use the clientData (You can set your own key name) as the key and the
// entire item as the value
obj['clientData'] = item
return obj
}, {});
Here's how to dynamically accept the above as a string and interpolate it into an object:
var stringObject = '[Object { key="11", value="1100", $$hashKey="00X"}, Object { key="22", value="2200", $$hashKey="018"}]';
function interpolateStringObject(stringObject) {
var jsObj = {};
var processedObj = stringObject.split("[Object { ");
processedObj = processedObj[1].split("},");
$.each(processedObj, function (i, v) {
jsObj[v.split("key=")[1].split(",")[0]] = v.split("value=")[1].split(",")[0].replace(/\"/g,'');
});
return jsObj
}
var t = interpolateStringObject(stringObject); //t is the object you want
http://jsfiddle.net/3QKmX/1/
// original
var arr = [{
key: '11',
value: '1100',
$$hashKey: '00X'
},
{
key: '22',
value: '2200',
$$hashKey: '018'
}
];
// My solution
var obj = {};
for (let i = 0; i < arr.length; i++) {
obj[arr[i].key] = arr[i].value;
}
console.log(obj)
You can use the mapKeys lodash function for that. Just one line of code!
Please refer to this complete code sample (copy paste this into repl.it or similar):
import _ from 'lodash';
// or commonjs:
// const _ = require('lodash');
let a = [{ id: 23, title: 'meat' }, { id: 45, title: 'fish' }, { id: 71, title: 'fruit' }]
let b = _.mapKeys(a, 'id');
console.log(b);
// b:
// { '23': { id: 23, title: 'meat' },
// '45': { id: 45, title: 'fish' },
// '71': { id: 71, title: 'fruit' } }

How can I reduce elements in object?

I have an object like this:
result:
> rows:
> 0: {key: Array(4), value: 3}
> key: (4) ["Person", "2020-06-24", "Product, "00000000008"]
value: 3
> 1: {key: Array(4), value: 10}
> key: (4) ["Person", "2020-06-25", "Product, "00000000009"]
value: 10
> 2: {key: Array(4), value: 10}
> key: (4) ["Person", "2020-06-25", "Product, "00000000008"]
value: 10
Now, what I need to do is to reduce this result checking for the same code (for example 00000000008) and sum the value, to obtain:
(for example)
00000000008 value: 13
Now, my problem is how to do, I have tried to use first a map and then a reduce, but I don't understand how can I check for the same code and sum the value.
How can I do?
I have tried in this way, but it doesn't work:
res is the object with the values
let example = res.rows.map((element)=> {
console.log("ELEMENT IS ", element)
let example1 = element.key[3].reduce(function(element, v){
if(ref.hasOwnProperty(v))
element[ref[v]] += v;
else {
ref[v] = element.length;
element.push(prev = v)
}
return element
}, [])
})
console.log("element", element)
The Array.map method is useful for data transformations, but if you have to aggregate is mostly expensive because you have also to Array.filter the non-aggregated values.
You can use Array.reduce (MDN) instead in order to build your own object:
let result = {
rows: [
{
key: ["Person", "2020-06-24", "Product", "00000000008"],
value: 3
},
{
key: ["Person", "2020-06-25", "Product", "00000000009"],
value: 10
},
{
key: ["Person", "2020-06-25", "Product", "00000000008"],
value: 10
}
]
}
let output1 = result.rows.reduce((acc, current) => {
let key = current.key[3];
// adding value to the accumulator
acc[key] = (acc[key] || 0) + current.value;
return acc;
}, {});
console.log(output1);
let output2 = result.rows.reduce((acc, current) => {
// check if key is already present
let found = acc.find(v => v.key == current.key[3])
// if it is, update the current value
if (found) {
found.value += current.value;
}
// otherwise create a new one
else {
acc.push({ key: current.key[3], value: current.value });
}
return acc;
}, []);
console.log(output2)
create your own hashmap and loop over the result object once for all values
const hashmap = {};
rows.forEach(v => {
hashmap[v.product] = (hashmap[v.product] || 0) + v.value;
});
// then are you able to access any product value on O(1)
const total = hashmap['00000000008'];
console.log({total});
// total: 13

How to detect object differences between two arrays?

I'm trying to compare two arrays of objects and returns a list of updated objects. I don't want to use lodash just the javascript data structures and functions.
E.g:
I have a first array which named arr1 = [
{
name: 'attribute 1',
id: 12,
value: 40,
docs:[],
version: 1,
},
{
name: 'attribute 41',
id: 12,
value: 6,
version: 1,
}
]
And another array:
array2 = [
{
name: 'attribute 1',
attributeTypeId: 12,
value: 65,
docs: ['bla bla']
}
]
I'm trying to iterate through the two arrays and detect the differences and returns an array like that:
result = [
{
name: 'attribute 1',
id: 12,
value: 65,
docs:['bla bla'],
version: 1,
},
{
name: 'attribute 41',
id: 12,
value: 6,
version: 1,
}]
I wrote some uncomplete function (not optimized yet just a brute force solution):
const filterProperties = (e) => {
return e.toLowerCase() !== 'name' && e.toLowerCase() !== 'id'
}
// function sort
const sortProperties = (a, b) => a < b ? -1 : 1;
let result = []
attributesUpdate.forEach(attr => {
const attrProps = Object.getOwnPropertyNames(attr);
// iterate the attributes
for (let i = 0; i < attributes.length; i++) {
let attribute = attributes[i];
// check if the attribute to update has a different name or attributeTypeId
if (attribute.name !== attr.name) {
result = result.concat(attr);
}
// check if the attribute to update has the same name, id
// of the originalOne
if (attribute.name === attr.name && attribute.id=== attr.id) {
let obj = {
name: attribute.name,
id: attribute.id,
}
// get the properties of the attribute
const attributeProps = Object.getOwnPropertyNames(attribute);
// extract the name and id from the list
const filtredAttributeProps = attributeProps.filter(filterProperties);
const filteredattrProps = attrProps.filter(filterProperties);
// returns the length of each array of properties
const attrLength = filteredattrProps.length;
const attributeLength = filtredAttributeProps.length;
if (attrLength === attributeLength) {
for (let j = 0; j < attrLength; j++) {
const propName = filteredattrProps[j];
obj[propName] = attr[propName];
}
result = result.filter(e => e.name === attr.name
&& e.id=== attr.id)
.map(e => Object.assign(e, {obj}))
}
if (attrLength !== attributeLength) {
// sort the array of properties
const sortedAttrProps = filteredattrProps.sort(sortProperties);
const sortedAttributeProps = filtredAttributeProps.sort(sortProperties);
// check the shortest object
const min = attrLength < attributeLength ? attrLength : attributeLength;
// get the biggest object
const longestObjProps = attrLength === min ? sortedAttributeProps : sortedAttrProps;
const longestObj = attrLength === min ? attribute : attr
const shortestProps = attrLength === min ? sortedAttrProps: sortedAttributeProps;
const shortestObj = attrLength === min ? attr : attribute
// fill the object with attr properties
for(let j = 0; j < min; j++) {
const propName = shortestProps[j];
obj[propName] = shortestObj[propName];
}
// fill the remaining properties in the object
const remainingProperties = longestObjProps.filter(e => !shortestProps.includes(e));
for (let j = 0; j < remainingProperties.length; j++) {
const propName = remainingProperties[j];
obj[propName] = longestObj[propName]
}
if (!result.length || result.filter(e => e.name !== attr.name &&
e.id!== attr.id).length === 0) {
result.concat(obj);
}
}
}
}
})
console.log('result: ', result);
I got such a result :
[
{
name: 'attribute 1',
attributeTypeId: 12,
value: 65,
docs: ['bla bla']
}
]
How can I fix this code to get the desired results? I hope that my question will not be downvoted. Any suggestion will be welcome.
What this code does is loop through the objects in array2, and then when it finds that there is a matching name/id in arr1, it simply updates the properties of that object. If not found, it will add the object to arr1.
arr1 = [{
name: 'attribute 1',
id: 12,
value: 40,
docs: [],
version: 1,
},
{
name: 'attribute 41',
id: 12,
value: 6,
version: 1,
}
];
array2 = [{
name: 'attribute 1',
attributeTypeId: 12,
value: 65,
docs: ['bla bla']
}];
updateArray(arr1, array2);
console.log(arr1);
function updateArray(arrayToUpdate, dataToUpdateWith) {
dataToUpdateWith.forEach(function(obj) {
var objToUpdate = checkIfNameIdExists(arrayToUpdate, obj.name, obj.attributeTypeId);
if (objToUpdate === false) {
objToUpdate = obj;
arrayToUpdate.push(objToUpdate);
} else {
for (var prop in obj) {
if (objToUpdate.hasOwnProperty(prop)) {
var nameInFinalObject = prop;
if (prop === "attributeTypeId") {
nameInFinalObject = "id";
}
objToUpdate[nameInFinalObject] = obj[prop];
}
}
}
});
}
function checkIfNameIdExists(arrOfObj, name, id) {
if (name === null) {
return false;
}
var output = false;
arrOfObj.forEach(function(obj) {
if (obj.name === name) {
output = obj;
return true;
}
});
return output;
}
Assumptions:
The values in each of the objects are same type and values are not nested so there is a need to recursively traverse the tree to compare equality etc.
The first array is the source and the subsequent (with the same name) is the mutated form.
We are not handling removals of properties from the source object. From what is given by the OP we are only accounting for value changes.
const d1 = [{ name: 'attribute 1', id: 12, value: 40, docs: [], version: 1, }, { name: 'attribute 41', id: 12, value: 6, version: 1, } ]
const d2 = [{ name: 'attribute 1', attributeTypeId: 12, value: 65, docs: ['bla bla'] }]
const isChanged = (a, b) =>
Array.isArray(a) ? !a.every(x => b.includes(x)) : a !== b
const compare = (o1, o2) => Object.entries(o1).reduce((r, [k,v]) => {
if(k in o2 && isChanged(o2[k], v))
Object.assign(r, {[k]: o2[k]})
return r
}, o1)
const group = (a, b) => [...a, ...b].reduce((r,c) =>
(r[c.name] = [...r[c.name] || [], c], r), {})
const result = Object.values(group(d1,d2)).reduce((r,c) =>
(r.push(c.length == 2 ? compare(...c) : c[0]), r), [])
console.log(result)
The idea is to merge the objects in one array, group them by name and if there ware any changes the groups with length of 2 would be compared by the compare function. Otherwise just added to the end result.

Remove Object From Array if the value is empty in name and value pair js

[{name: "mode", value: "1"},{name: "group", value: ""},{name: "from_date", value: ""},{name: "to_date", value: "2018-10-16"},{name: "action", value: "ac_filter_transactions"}
This is how my array looks like. I want to remove the name and value pair from the array if the value is empty.
I tried this solution: but this didn't work
formData.map((i) => {
(i.value == "") ? delete i: "";
});
I know this is a simple question but I couldn't find any relevant example to solve this problem. All examples and solutions I found was for this type of object
let obj = {"firstname": "XYZ", "lastname": "ABC"}
What are the difference between both the objects?
You can use Array.prototype.filter and return entries based on a boolean of whether or not the value exists since an empty string is falsy.
a.filter(o => (o.value));
let a = [{name: "mode", value: "1"},{name: "group", value: ""},{name: "from_date", value: ""},{name: "to_date", value: "2018-10-16"},{name: "action", value: "ac_filter_transactions"}];
let result = a.filter(o => (o.value));
console.log(result);
Note: If the any of your value properties are also falsy, they won't be picked up either. To get around this you could simply rewrite it using: (o.value !== "")
let a = [{name: "mode", value: "1"},{name: "group", value: ""},{name: "from_date", value: ""},{name: "to_date", value: "2018-10-16"},{name: "action", value: "ac_filter_transactions"}];
let result = a.filter(o => (o.value !== ""));
console.log(result);
For your question title I assume "remove" means mutate the array (change its actual content). If it is so you can do it like this:
const copy = arr.slice(); // copy of array for iterating without getting the index (`i`) wrong
let count = 0;
copy.forEach((val, i) => { if (!val.value) arr.splice(i - count++, 1); });
// maybe `val.value != ""` instead of `!val.value` ?
Demo:
var arr = [{name: "mode",value: "1"}, {name: "group", value: ""}, {name: "from_date",value: ""}, {name: "to_date", value: "2018-10-16"}, {name: "action",value:"ac_filter_transactions"}];
const copy = arr.slice();
let count = 0;
copy.forEach((val, i) => { if (!val.value) arr.splice(i - count++, 1); });
console.log(arr); // print original array, not a copy
Or if you do not want to mutate the array (do not change its actual content) then you can just make a (filtered) copy of it like this:
const copy = arr.filter(val => !!val.value)
Demo:
var arr = [{name: "mode",value: "1"}, {name: "group", value: ""}, {name: "from_date",value: ""}, {name: "to_date", value: "2018-10-16"}, {name: "action",value:"ac_filter_transactions"}];
console.log(arr.filter(val => !!val.value)); // print a copy, not the original array
Array.map will return the same number of items in a new array. So, you would need to use Array.reduce instead.
formData.reduce((result, item) => {
if (item.value) {
result.push(item);
}
return result;
}, []);

retriving values from javascript object and then convert it to one object

I have a problem! I am creating an rating app, and I have come across a problem that I don't know how to solve. The app is react native based so I am using JavaScript.
The problem is that I have multiple objects that are almost the same, I want to take out the average value from the values of the "same" objects and create a new one with the average value as the new value of the newly created object
This array in my code comes as a parameter to a function
var arr = [
{"name":"foo","value":2},
{"name":"foo","value":5},
{"name":"foo","value":2},
{"name":"bar","value":2},
{"name":"bar","value":1}
]
and the result I want is
var newArr = [
{"name":"foo","value":3},
{"name":"bar","value":1.5},
]
If anyone can help me I would appreciate that so much!
this is not my exact code of course so that others can take help from this as well, if you want my code to help me I can send it if that's needed
If you have any questions I'm more than happy to answer those
Iterate the array with Array.reduce(), and collect to object using the name values as the key. Sum the Value attribute of each name to total, and increment count.
Convert the object back to array using Object.values(). Iterate the new array with Array.map(), and get the average value by dividing the total by count:
const arr = [{"name":"foo","Value":2},{"name":"foo","Value":5},{"name":"foo","Value":2},{"name":"bar","Value":2},{"name":"bar","Value":1}];
const result = Object.values(arr.reduce((r, { name, Value }) => {
if(!r[name]) r[name] = { name, total: 0, count: 0 };
r[name].total += Value;
r[name].count += 1;
return r;
}, Object.create(null)))
.map(({ name, total, count }) => ({
name,
value: total / count
}));
console.log(result);
I guess you need something like this :
let arr = [
{name: "foo", Value: 2},
{name: "foo", Value: 5},
{name: "foo", Value: 2},
{name: "bar", Value: 2},
{name: "bar", Value: 1}
];
let tempArr = [];
arr.map((e, i) => {
tempArr[e.name] = tempArr[e.name] || [];
tempArr[e.name].push(e.Value);
});
var newArr = [];
$.each(Object.keys(tempArr), (i, e) => {
let sum = tempArr[e].reduce((pv, cv) => pv+cv, 0);
newArr.push({name: e, value: sum/tempArr[e].length});
});
console.log(newArr);
Good luck !
If you have the option of using underscore.js, the problem becomes simple:
group the objects in arr by name
for each group calculate the average of items by reducing to the sum of their values and dividing by group length
map each group to a single object containing the name and the average
var arr = [
obj = {
name: "foo",
Value: 2
},
obj = {
name: "foo",
Value: 5
},
obj = {
name: "foo",
Value: 2
},
obj = {
name: "bar",
Value: 2
},
obj = {
name: "bar",
Value: 1
}
]
// chain the sequence of operations
var result = _.chain(arr)
// group the array by name
.groupBy('name')
// process each group
.map(function(group, name) {
// calculate the average of items in the group
var avg = (group.length > 0) ? _.reduce(group, function(sum, item) { return sum + item.Value }, 0) / group.length : 0;
return {
name: name,
value: avg
}
})
.value();
console.log(result);
<script src="http://underscorejs.org/underscore-min.js"></script>
In arr you have the property Value and in newArr you have the property value, so I‘ll assume it to be value both. Please change if wished otherwise.
var map = {};
for(i = 0; i < arr.length; i++)
{
if(typeof map[arr[i].name] == ‘undefined‘)
{
map[arr[i].name] = {
name: arr[i].name,
value: arr[i].value,
count: 1,
};
} else {
map[arr[i].name].value += arr[i].value;
map[arr[i].name].count++;
}
var newArr = [];
for(prop in map)
{
map[prop].value /= map[prop].count;
newArr.push({
name: prop,
value: map[prop].value
});
}
delete map;

Categories