I have an object array containing one property call name like this
var nameArr = [
{
"name":"john"
},
{
"name":"carl"
},
{
"name":"peter"
}
]
I have a another array called ageArr and it only contain property called age
var ageArr = [
{
"age":"22"
},
{
"age":"21"
},
{
"age":"32"
}
]
i want to concat these array and end result should result like this
var result = [
{
"age":"22",
"name":"john"
},
{
"age":"21",
"name":"carl"
},
{
"age":"32",
"name":"peter"
}
]
note that length of the both arrays always equal and dynamic. Is there any way i can do this without looping these array inside one another. Thank you.
You can use Object.assign() and map() and return new array.
var nameArr = [{"name":"john"},{"name":"carl"},{"name":"peter"}]
var ageArr = [{"age":"22"},{"age":"21"},{"age":"32"}]
var result = nameArr.map(function(e, i) {
return Object.assign({}, e, ageArr[i])
})
console.log(result)
Single forEach() function is enough.
var nameArr=[{name:"john"},{name:"carl"},{name:"peter"}],
ageArr=[{age:"22"},{age:"21"},{age:"32"}];
nameArr.forEach((v,i) => v.age = ageArr[i].age)
console.log(nameArr);
You can use the following code snippet.
var result = nameArr.map(function( obj, index ) {
var res = ageArr[index];
res.name = obj.name;
return res;
});
In the map, you can easily use
jQuery.extend()
to create a merge of two same index object.
Related
Problem
I would like to have the below two JSON combined together using the ID and have the expected result as mentioned below. I have tried a few solutions that were available but none worked for my use case. Any suggestions will be great !!
Tried to do:
How to merge two json object values by id with plain Javascript (ES6)
Code
var json1 = [
{
"id":"A123",
"cost":"5020.67",
"fruitName":"grapes"
},
{
"id":"A456",
"cost":"341.30",
"fruitName":"apple"
},
{
"id":"A789",
"cost":"3423.04",
"fruitName":"banana"
}
];
var json2 = [
{
"id":"A123",
"quantity":"7"
},
{
"id":"A789",
"quantity":"10"
},
{
"id":"ABCD",
"quantity":"22"
}
];
Below is the code I tried:
var finalResult = [...[json1, json2].reduce((m, a) => (a.forEach(o => m.has(o.id) && Object.assign(m.get(o.id), o) || m.set(o.id, o)), m), new Map).values()];
Expected result:
[
{
"id":"A123",
"cost":"5020.67",
"fruitName":"grapes",
"quantity":"7"
},
{
"id":"A456",
"cost":"341.30",
"fruitName":"apple"
},
{
"id":"A789",
"cost":"3423.04",
"fruitName":"banana",
"quantity":"10"
},
{
"id":"ABCD",
"quantity":"22"
}
]
You can accomplish this fairly easily without getting too fancy. Here's the algorithm:
Put the items from json1 into an object by id, so that you can look them up quickly.
For each item in json2: If it already exists, merge it with the existing item. Else, add it to objectsById.
Convert objectsById back to an array. I've used Object.values, but you can also do this easily with a loop.
var json1 = [
{
"id":"A123",
"cost":"5020.67",
"fruitName":"grapes"
}, {
"id":"A456",
"cost":"341.30",
"fruitName":"apple"
}, {
"id":"A789",
"cost":"3423.04",
"fruitName":"banana"
}
];
var json2 = [
{
"id":"A123",
"quantity":"7"
}, {
"id":"A789",
"quantity":"10"
}
];
const objectsById = {};
// Store json1 objects by id.
for (const obj1 of json1) {
objectsById[obj1.id] = obj1;
}
for (const obj2 of json2) {
const id = obj2.id;
if (objectsById[id]) {
// Object already exists, need to merge.
// Using lodash's merge because it works for deep properties, unlike object.assign.
objectsById[id] = _.merge(objectsById[id], obj2)
} else {
// Object doesn't exist in merged, add it.
objectsById[id] = obj2;
}
}
// All objects have been merged or added. Convert our map to an array.
const mergedArray = Object.values(objectsById);
I think a few steps are being skipped in your reduce function. And it was a little difficult to read because so many steps are being combined in one.
One critical piece that your function does not account for is that when you add 2 numerical strings together, it concats the strings.
const stringTotal = "5020.67" + "3423.04" // result will be "5020.673423.04"
The following functions should give you the result you are looking for.
// calculating the total cost
// default values handles cases where there is no obj in array 2 with the same id as the obj compared in array1
const calcualteStringTotal = (value1 = 0, value2 = 0) => {
const total = parseFloat(value1) + parseFloat(value2)
return `${total}`
}
const calculateTotalById = (array1, array2) => {
const result = []
// looping through initial array
array1.forEach(outterJSON => {
// placeholder json obj - helpful in case we have multiple json in array2 with the same id
let combinedJSON = outterJSON;
// looping through second array
array2.forEach(innerJSON => {
// checking ids
if(innerJSON.id === combinedJSON.id) {
// calls our helper function to calculate cost
const updatedCost = calcualteStringTotal(innerJSON.cost, outterJSON.cost)
// updating other properties
combinedJSON = {
...outterJSON,
...innerJSON,
cost: updatedCost
}
}
})
result.push(combinedJSON)
})
return result
}
const combinedResult = calculateTotalById(json1, json2)
I figured that by using reduce I could make it work.
var finalResult = [...[json1, json2].reduce((m, a) => (a.forEach(o => m.has(o.id) && Object.assign(m.get(o.id), o) || m.set(o.id, o)), m), new Map).values()];
I have an array of objects that looks something like
{
"foo":[
{
"bar":"boo"
},
{
"baz":"bang"
}
]
}
I want to update baz with a new value but I cannot work out how to merge both these objects?
I tried something like Object.assign({}, foo,{baz: 'beep'})
But this did not work?
foo is an Array of objects to replace it with new value, try the following:
var obj = { "foo":[ { "bar":"boo" }, { "baz":"bang" } ] };
var index = obj.foo.findIndex((o) =>Object.keys(o).includes("baz"));
if(index != -1)
Object.assign(obj.foo[index], {baz: 'beep'});
console.log(obj);
Assuming you don't necessarily know the array index of the element you're trying to modify, you'll need to search through that array to find it -- for example using Array.find():
let quux = {
"foo":[
{
"bar":"boo"
},
{
"baz":"bang"
}
]
}
quux.foo.find(
(obj) => {
return obj.baz === "bang"
}
).baz="beep";
console.log(quux);
// This mutates the original object; if you need a clone wrap this in an Object.assign as shown in other answers
(Arrays of objects can be inconvenient for this reason; you may be better off with an object of objects, so there's an ID for each.)
If you're trying to create a modified copy of foo, use Array.prototype.map:
const foo = [
{
"bar":"boo"
},
{
"baz":"bang"
}
];
const newFoo = foo.map(value => {
if('baz' in value) return Object.assign({}, value, {a: 'b'});
return value;
});
console.log(newFoo);
I am trying to use reduce() for getting economy rate for a particular wicket.
Example data:
var data = [
{wicket:0, econ:20 },
{wicket:1, econ:10 },
{wicket:3, econ:45 },
{wicket:0, econ:15 },
{wicket:1, econ:32 }
]
I want reduce() method to return an array of objects which will look like this:
0: 20, 15
1: 10, 32
3: 45
What I am trying to do is initialize accumulator with object but in reduce() method I am not able to figure out how can I get the required array of objects with key value as wicketand values as economy.
My code:
const Economy = data.reduce( (a, {econ, wicket}) => {
a[wicket].push(econ);
},{})
I get undefined behaviour with above code.
If your data was meant to be an Array and not an Object (which it isn't right now, at least not a valid one) :
let data = [
{wicket:0, econ:20 },
{wicket:1, econ:10 },
{wicket:3, econ:45 },
{wicket:0, econ:15 },
{wicket:1, econ:32 }
];
let result = data.reduce((acc, curr) => {
if(acc[curr.wicket]) acc[curr.wicket].push(curr.econ);
else acc[curr.wicket] = [curr.econ];
return acc;
},{});
console.log(result);
You can use group the array using reduce like:
var data = [{"wicket":0,"econ":20},{"wicket":1,"econ":10},{"wicket":3,"econ":45},{"wicket":0,"econ":15},{"wicket":1,"econ":32}];
var result = data.reduce((c, v) => {
c[v.wicket] = c[v.wicket] || []; //Initiate the property as empty array of it does not exist
c[v.wicket].push(v.econ);
return c;
}, {});
console.log(result);
|| is an OR operator.
This means if c[v.wicket] exist, it will assign it to c[v.wicket] again. If it does not, assign an empty array []
c[v.wicket] = c[v.wicket] || [];
I have this JavaScript array:
[ "124857202", "500255104", "78573M104" ]
I want to convert this particular array into an array of objects as shown below:
[
{ name: "124857202" },
{ name: "500255104" },
{ name: "78573M104" }
]
Use Array#map to convert each value into a different value:
var newArr = arr.map(function(value) {
return {name: value};
});
Array#map applies the callback to each element in the array and returns a new array containing the return values of the callback.
I would take a look at the array.map function in javascript.
const mappedArr = arr.map(value => {
return {
name: value
}
})
I want to convert this particular array into an array of objects as
shown below
If you want to change the actual array in place (rather than creating a new array), you can use a for loop to iterate the indexes of your array. For each index, you can replace the value with an object {name: arr[i]}. This object has a name key, and takes a value which is the current element arr[i].
const arr = [ "124857202", "500255104", "78573M104" ];
for(let i = 0; i < arr.length; i++) {
arr[i] = {name: arr[i]};
}
console.log(arr);
Or, if you want to make a new array and leave the original untouched, you can use Felix's answer, here it can be re-written to use more modern ES6 features to make it more concise, such as an arrow function and shorthand property names:
const arr = [ "124857202", "500255104", "78573M104" ];
const res = arr.map(name => ({name}));
console.log(res);
Another approach - Array#reduce.
var arr = ["124857202", "500255104", "78573M104"];
var res = arr.reduce(function(s, a){
s.push({name: a});
return s;
}, [])
console.log(res);
You can use
var arrayOfStrings = ["124857202", "500255104", "78573M104"];
var arrayOfObjects = [];
arrayOfStrings.forEach(function (element, index) {
arrayOfObjects.push({
name: element,
})
});
Felix Kling' answer, gehsekky's answer and the second part of Nick Parsons' answer are the most correct. For completeness, here is a version that uses Underscore's _.map:
import { map } from 'underscore';
var result = map(array, name => ({name}));
For this particular use case, _.map doesn't buy you much compared to Array.prototype.map except for a little bit of added portability. Going the other way, however, is a bit easier on the brain with _.map because of Underscore's iteratee shorthands:
// Underscore map
var array = map(result, 'name');
// Array.prototype.map
var array = result.map(obj => obj.name);
Underscore's map and other collection functions really shine when you need to iterate over a plain object, since JavaScript's built-in methods don't support this at all:
var objectOfStrings = {
first: "124857202",
second: "500255104",
third: "78573M104"
};
// to array of strings, Underscore
var arrayOfStrings = map(objectOfStrings);
// to array of strings, vanilla JS
var arrayOfStrings = [], value;
for (key in objectOfStrings) {
arrayOfStrings.push(objectOfStrings[key]);
}
// to array of objects, Underscore
var arrayOfObjects = map(objectOfStrings, name => ({name}));
// to array of objects, vanilla JS
var arrayOfStrings = [], name;
for (key in objectOfStrings) {
name = objectOfStrings[key];
arrayOfStrings.push({name});
}
var objectOfObjects = {
first: {name: "124857202"},
second: {name: "500255104"},
third: {name: "78573M104"}
};
// to array of strings, Underscore
var arrayOfStrings = map(objectOfStrings, 'name');
// to array of strings, vanilla JS
var arrayOfStrings = [], value;
for (key in objectOfObjects) {
arrayOfStrings.push(objectOfObjects[key].name);
}
// to array of objects, Underscore
var arrayOfObjects = map(objectOfObjects);
// to array of objects, vanilla JS
var arrayOfObjects = [], value;
for (key in objectOfStrings) {
arrayOfObjects.push(objectOfStrings[key]);
}
I am trying to reduce a JSON array. Inside the array are other object, I am trying to turn the attributes into their own array.
Reduce Function:
// parsed.freight.items is path
var resultsReduce = parsed.freight.items.reduce(function(prevVal, currVal){
return prevVal += currVal.item
},[])
console.log(resultsReduce);
// two items from the array
// 7205 00000
console.log(Array.isArray(resultsReduce));
// false
The reduce function is kind of working. It gets both item from the items array. However I am having a couple problems.
1) The reduce is not passing back an array. See isArray test
2) I am trying to make a function so I can loop through all of the attributes in the array the qty, units, weight, paint_eligable. I cannot pass a variable to the currVal.variable here
Attempting:
var itemAttribute = 'item';
var resultsReduce = parsed.freight.items.reduce(function(prevVal, currVal){
// pass param here so I can loop through
// what I actually want to do it create a function and
// loop through array of attributes
return prevVal += currVal.itemAttribute
},[])
JSON:
var request = {
"operation":"rate_request",
"assembled":true,
"terms":true,
"subtotal":15000.00,
"shipping_total":300.00,
"taxtotal":20.00,
"allocated_credit":20,
"accessorials":
{
"lift_gate_required":true,
"residential_delivery":true,
"custbodylimited_access":false
},
"freight":
{
"items":
// array to reduce
[{
"item":"7205",
"qty":10,
"units":10,
"weight":"19.0000",
"paint_eligible":false
},
{ "item":"1111",
"qty":10,
"units":10,
"weight":"19.0000",
"paint_eligible":false
}],
"total_items_count":10,
"total_weight":190.0},
"from_data":
{
"city":"Raleigh",
"country":"US",
"zip":"27604"},
"to_data":
{
"city":"Chicago",
"country":"US",
"zip":"60605"
}
}
Thanks in advance
You may need Array#map for getting an array of items
var resultsReduce = parsed.freight.items.reduce(function (array, object) {
return array.concat(object.item);
}, []);
The same with a given key, with bracket notation as property accessor
object.property
object["property"]
var key = 'item',
resultsReduce = parsed.freight.items.reduce(function (array, object) {
return array.concat(object[key]);
}, []);