I am new to javascript and I want to loop through json data and add accumulative number to the end of it.
Here is a sample dataset:
[{'a':123,'b':345,'c':{'b1':1,'b2':2,'b3':3}},
{'a':234,'b':456,'c':{'b1':2,'b2':4,'b3':6}},
{'a':345,'b':567,'c':{'b1':3,'b2':6,'b3':9}}]
And this is what I want to achieve:
[{'a':123,'b':345,'c':{'b1':1,'b2':2,'b3':3},'d':345+1+2+3},
{'a':234,'b':456,'c':{'b1':2,'b2':4,'b3':6},'d':456+2+4+6},
{'a':345,'b':567,'c':{'b1':3,'b2':6,'b3':9},'d':567+3+6+9}]
Use Array.map() to iterate the array, and generate new objects that contain the property d. For each object in the array, use destructuring with rest to assign a value to a property, and the rest of the properties to an object (named rest in this case).
Create a new object, using a and rest (by spreading it), and add the d property, which is the sum of all rest properties.
To sum object properties recursively I've added the sumProps method. The function uses Object.values() to get an array of values. Then it iterates an sum them using Array.reduce(). Unless a value is an object, in which case we run it through sumProps again.
const data = [
{'a':123,'b':345,'c':{'b1':1,'b2':2,'b3':3}},
{'a':234,'b':456,'c':{'b1':2,'b2':4,'b3':6}},
{'a':345,'b':567,'c':{'b1':3,'b2':6,'b3':9}}
];
const sumProps = (o) =>
Object.values(o) // get the values of an object
.reduce((r, v) => // iterate the values
r + (typeof v === 'object' ? sumProps(v) : v) // add the values to the previous sum, and if the values are an object sum it recursively
, 0);
// iterate the objects with map
const result = data.map(({ a, ...rest }) => { // destructure a, and an object of all other params
return ({ // combine them back to an object
a,
...rest, // spread the rest object
d: sumProps(rest) // get the sum of the rest, and assign to d
});
});
console.log(result);
Related
I have the below json data array:
[{"name":"Button1","date":"1596959802144"},{"name":"Button2","date":"1596959804238"},{"name":"Button3","date":"1596959809334"},{"name":"Button1","date":"1597000878135"},{"name":"Button2","date":"1597000896335"},{"name":"Button3","date":"1597000901536"},{"name":"Button2","date":"1597000904437"},{"name":"Button3","date":"1597000909535"},{"name":"Button1","date":"1597000912250"},{"name":"Button2","date":"1597000939937"},{"name":"Button3","date":"1597000957940"},{"name":"Button2","date":"1597000964640"},{"name":"Button1","date":"1597001005141"},{"name":"Button2","date":"1597001010240"},{"name":"Button3","date":"1597001014845"},{"name":"Button2","date":"1597001021644"},{"name":"Button1","date":"1597001025738"},{"name":"Button2","date":"1597001049030"},{"name":"Button3","date":"1597001054139"},{"name":"Button1","date":"1597001057741"},{"name":"Button2","date":"1597001060340"},{"name":"Button3","date":"1597001062445"},{"name":"Button1","date":"1597002599045"},{"name":"Button1","date":"1597002604128"},{"name":"Button1","date":"1597002609546"},{"name":"Button1","date":"1597002613435"},{"name":"Button1","date":"1597002681736"},{"name":"Button1","date":"1597002690843"},{"name":"Button1","date":"1597002694136"},{"name":"Button1","date":"1597002696349"},{"name":"Button1","date":"1597002699243"}]
and I would like to use JMESPath javascript library to get only the last 3 entries per each distinct name value. For example:
[{"name":"Button3","date":"1597001014845"},{"name":"Button2","date":"1597001021644"},{"name":"Button2","date":"1597001049030"},{"name":"Button3","date":"1597001054139"},{"name":"Button2","date":"1597001060340"},{"name":"Button3","date":"1597001062445"},{"name":"Button1","date":"1597002694136"},{"name":"Button1","date":"1597002696349"},{"name":"Button1","date":"1597002699243"}]
So the last 3 occurrences fro each name = Button*
checking on stackOverflow and I saw that with JQ is possible to do using this function: map_values(delpaths(keys_unsorted[:-2] | map([.])))
Get last N elements for each item of a JSON object
Is there any way to do? or using other javascript module?
If you don't care about the order in your resulting array, here would be a pure JavaScript way to do this:
const getLastNForEveryName = (arr, n) => {
const lastNOfEach = arr.reduce((acc, curr) => {
if(acc[curr.name] == null) { // If the key doesnt exist yet, create it with the current item in the array
acc[curr.name] = [curr];
} else {
if(acc[curr.name].length >= n) // If the array is as big as the desired size alread, remove the first added one
acc[curr.name].shift();
acc[curr.name].push(curr); // push the current item in the array
}
return acc;
}, {})
return Object.values(lastNOfEach).flatMap(l => l); // Just get the values of the object and flatMap it, so that we dont have arrays of arrays
}
// Testing
const values = [{"name":"Button1","date":"1596959802144"},{"name":"Button2","date":"1596959804238"},{"name":"Button3","date":"1596959809334"},{"name":"Button1","date":"1597000878135"},{"name":"Button2","date":"1597000896335"},{"name":"Button3","date":"1597000901536"},{"name":"Button2","date":"1597000904437"},{"name":"Button3","date":"1597000909535"},{"name":"Button1","date":"1597000912250"},{"name":"Button2","date":"1597000939937"},{"name":"Button3","date":"1597000957940"},{"name":"Button2","date":"1597000964640"},{"name":"Button1","date":"1597001005141"},{"name":"Button2","date":"1597001010240"},{"name":"Button3","date":"1597001014845"},{"name":"Button2","date":"1597001021644"},{"name":"Button1","date":"1597001025738"},{"name":"Button2","date":"1597001049030"},{"name":"Button3","date":"1597001054139"},{"name":"Button1","date":"1597001057741"},{"name":"Button2","date":"1597001060340"},{"name":"Button3","date":"1597001062445"},{"name":"Button1","date":"1597002599045"},{"name":"Button1","date":"1597002604128"},{"name":"Button1","date":"1597002609546"},{"name":"Button1","date":"1597002613435"},{"name":"Button1","date":"1597002681736"},{"name":"Button1","date":"1597002690843"},{"name":"Button1","date":"1597002694136"},{"name":"Button1","date":"1597002696349"},{"name":"Button1","date":"1597002699243"}];
console.log(getLastNForEveryName(values, 3));
Hello I am new in react native and I want to merge data using Object.assign().
I tried with simple arrays and everythings work but my array is more than array in one big array.
My code:
let o1 = getCartData; // [{productId:56, productQuantity:1}, {productId:4, productQuantity:1}]
let o2 = resultObject; // product with different quantity {productId:56, productQuantity:5}
let finalObj = Object.assign([], o1, o2);
console.log('Final', finalObj); // Output ▼["[","{",""","p","r","o","d","u","c","t","I","d",""",":","5","6",",",""","p","r","o","d","u","c","t","Q","u","a","n","t","i","t","y",""",":","1","}","]"]
I want to get this output:
console.log('Final', finalObj); // Merged [{productId:56, productQuantity:5}, {productId:4, productQuantity:1}]
I tried based on this page
You can map it, Please let me know if this is what you need:
var obj1=[{productId:56, productQuantity:1}, {productId:4, productQuantity:1}];
var obj2={productId:56, productQuantity:5};
var result = obj1.map(({productId, productQuantity})=>({ productId, productQuantity: obj2[`productId`]==productId ? obj2.productQuantity : productQuantity}));
console.log(result);
Or you can make use of reduce method to group data:
var obj1=[{productId:56, productQuantity:1}, {productId:4, productQuantity:1}];
var obj2={productId:56, productQuantity:5};
var result = [...obj1, obj2].reduce((acc, {productId, productQuantity})=>{
acc[productId] = acc[productId] || {productId, productQuantity};
acc[productId].productQuantity = productQuantity;
return acc;
},{});
console.log(Object.values(result));
You can do this using map and find:
arr1.map(arrObj => arr2.find(arr2Obj => arr2Obj.productId === arrObj.productId) || arrObj);
What this code does is:
Inside the array of objects, it iterates through each object, in here each object is called arrObj.
For each object called arrObj we assign an operation using the arrow operator (=>), that operation is going to return a value.
Now we use array.find(()=>{}), which will seek on the second array and will search for every item inside the second array and we put a conditional for it, if the conditional is true, it will return the value of the found item, if not it will return null.
We use a (||) operator that will trigger when the item is not found, we return the object itself, as there is no other object found with the same Id.
Notice that this code works for comparing two arrays, in your example you are trying to compare an array with an object, it can be easily solved if your o2 is equal to [resultObject] (Inside the [brackets] to turn it into an array).
Got this solution from here: Replacing objects in array
i have an array like [x/0/2 , x/0/3 , y/3/1 , x/1/1 , x/0/3 , x/1/2],
i need to convert the elements range like [x/0/2-3 , y/3/1 , x/1/1-2]
Please give some suggestion for this.
Use reduce to iterate over the array and create an object grouped by the element root, then use Object.entries to pull out the correct information from the object.
const arr = ['x/0/2', 'x/0/3', 'y/3/1', 'x/1/1', 'x/0/3', 'x/1/2'];
const out = arr.reduce((acc, c) => {
// `split` out the separate parts of the element
const [ root1, root2, index ] = c.split('/');
// We'll use the first two parts as the object key
const key = `${root1}/${root2}`;
// If the key doesn't already exist create an empty
// array as its values
acc[key] = acc[key] || [];
// To prevent duplicates only add an index if it
// isn't already in the array
if (!acc[key].includes(index)) acc[key].push(index);
// Return the accumulator for the next iteration
return acc;
}, {});
// Then iterate over the object entries with `map`
const result = Object.entries(out).map(([ key, values ]) => {
// Return the joined up value
return `${key}/${values.join('-')}`;
});
console.log(result);
If I understand your question, you could create an array within the array to hold the range of values. Checking if the position in the array is an actual array let’s you know there are values that span a range within.
Example:
var values = [x/01, [x/20, x/21, x/22], x/03]
You could also create an object that could accomplish something similar depending on your needs.
I want to go through an array of strings, and depending on what the string is, make an array of objects.
For example, if the array is:
[a,a,a,b,b,c,d]
I want to map through the array and make an object with key and value pairs that add up the strings consecutively:
[{a:1},{a:2},{a:3},{b:1},{b:2},{c:1},{d:1}]
How do I do this?
I've tried mapping through, but I can't get how to add on to the previous object's value (a:1 -> a:2)
While mapping, you need to store a separate count of how many times each item has appeared, and increment the appropriate key each iteration. You might use a Map for this:
const input = ['a','a','a','b','b','c','d'];
const map = new Map();
console.log(
input.map(char => {
const count = (map.get(char) || 0) + 1;
map.set(char, count);
return { [char]: count };
})
)
I have an object like this:
I would like to do two things.
Sort the properties based on their values
I would to know the order (or index) for any given property. For example, after ordering, I would like to know that the index of 00D is the 5th.
How can I achieve this in JavaScript?
While you can not sort properties of an object, you could use an array of keys of the object, sort them and take the wanted element, you want.
var keys = Object.keys(object), // get all keys
indices = Object.create(null); // hash table for indices
// sort by value of the object
keys.sort(function (a, b) { return object[a] - object[b]; });
// create hash table with indices
keys.forEach(function (k, i) { indices[k] = i; });
// access the 5th key
console.log(keys[5]);
// get index of 00G
console.log(indices['00G']);