transform array to dynamic object - javascript

I would like to transform the following array which is dynamic to an dynamic object
e.g.
let
array=[{"MyFirstValue":"1"},{MySecondvalue:"2"}]
I would like to convert it ti an dynamic object
like
let newobject={MyFirstValue:"1",MySecondvalue:"2" }
The dynamic object here is that depending upon the numbers of values in the array the newobject should be able to transform
e.g.
if the array value changes =
array=[{"MyFirstValue":"1"},{MySecondvalue:"2"},{MyThirdValue:"2"}]
The newobject should transform to
newobject={MyFirstValue:"1",MySecondvalue:"2",MyThirdValue:"2" }
I tried using array.map and pushing the value but could not set the key property
It is like reducing the reducing the array to an object. I am not sure if i can use reduce.

You can accomplish this using Object.assign assuming your keys are unique.
const array = [{"key1":"1"}, {"key2":"2"}];
const newObject = Object.assign({}, ...array);
console.log(newObject);

You need to have unique keys in your object. Also, you should not expect all your objects to have 100% unique keys. Instead of having {key: 1, key: 2}, why not have the property key be an array of values; {key: [1, 2]}. I would use Array.prototype.reduce to achieve this.
const array = [{"key":"1", other: 'FOO'},{key:"2", dynamic: 'BAR', other: 'BAZ'}]
const object = array.reduce((initial, value) => {
Object.keys(value).forEach((key) => {
if(initial[key]) initial[key].push(value[key])
else initial[key] = [value[key]]
})
return initial;
}, {})
console.log(object)

try
let newobject= array.reduce((x,y)=> ({...x,...y}), {});
let array=[{"MyFirstValue":"1"},{MySecondvalue:"2"}]
let newobject= array.reduce((x,y)=> ({...x,...y}), {});
console.log(newobject);

Using ES5:
var input = [{"MyFirstValue":"1"},{MySecondvalue:"2"},{MyThirdValue:"2"}];
var output = Object.assign.apply({}, input);
console.log(output);

Related

Filtering one object with another array's object key

I am trying to filter an object with another object inside of an array.
To be more precise, I am trying to compare the keys of the object inside the array, to the keys of my main object. If the values are the same, I want to return the value corresponding to those keys.
Here's an example:
var a = {
"maths":"A++",
"literature":"C-",
"sports":"B+",
"biology":"D",
"chemistry":"A",
"english":"A+",
"physics":"C+"
}
var b = [{
"maths":"Mathematics",
"biology":"Biology",
"physics":"Physics"
}]
I wanna check if any of the keys in object b are inside object a and if they are, I want to return their value into array. For example, I want to return ["A++","D","C+"]
I've tried using filter and Array.prototype.some but I couldn't figure out anything. Any advice on how should I achieve this?
First make an array or Set of all the keys inside b, then use .map to access each key on the a object:
var a = {
"maths":"A++",
"literature":"C-",
"sports":"B+",
"biology":"D",
"chemistry":"A",
"english":"A+",
"physics":"C+"
}
var b = [{
"maths":"Mathematics",
"biology":"Biology",
"physics":"Physics"
}];
const keys = b.flatMap(Object.keys);
const arr = keys.map(key => a[key]);
console.log(arr);
I'm assuming that you want to handle multiple objects in b.
If so and if you want one array for each object in b then you could do something like:
var a = {
"maths":"A++",
"literature":"C-",
"sports":"B+",
"biology":"D",
"chemistry":"A",
"english":"A+",
"physics":"C+"
}
var b = [{
"maths":"Mathematics",
"biology":"Biology",
"physics":"Physics"
},{
"maths":"Mathematics",
"biology":"Biology",
"english":"English"
}]
const result = b.map(obj => Object.keys(obj).map(key => a[key]));
console.log(result);
If you are dealing with a single object in the array b, then you can do this:
var a = {
"maths":"A++",
"literature":"C-",
"sports":"B+",
"biology":"D",
"chemistry":"A",
"english":"A+",
"physics":"C+"
}
var b = [{
"maths":"Mathematics",
"biology":"Biology",
"physics":"Physics"
}]
const valuesInAndB = Object.keys(a).reduce((acc,x) => {
if (b[0][x]) {
return acc.concat(a[x]);
}
return acc;
}, []);
console.log(valuesInAndB);
However, if the objects in b will be greater than one then as answered by #certainperformance you could get all the keys in b and map through a with those keys.
const keysInB = b.flatMap(Object.keys);
keysInB.map(key => a[key]);
flatMap is not available in some older browsers, please keep that in mind.

How to merge 2 Objects taken by input's val

I have two JSON objects and I want to merge them:
Object1: {"9":{"322":{"option0":"177"}}}
Object2: {"10":{"323":{"option":"456"}}}
And I want for final result to be like:
{
"9": {
"322": {
"option0": "177"
}
},
"10": {
"323": {
"option": "456"
}
}
}
I tried the concat method, but the result is this:
{
"9":{
"322":{
"option0":"177"
}
}
}
{
"10":{
"323":{
"option":"456"
}
}
}
PS: The objects are taken by input like so:
var object1 = $('input').val();
Use Object.assign()
const Array1 = {"9":{"322":{"option0":"177"}}}
const Array2 = {"10":{"323":{"option":"456"}}}
let newObject = Object.assign({}, Array1, Array2);
console.log(newObject);
ES6 way:
const object1 = {"9":{"322":{"option0":"177"}}}
const object2 = {"10":{"323":{"option":"456"}}}
const object3 = { ...object1, ...object2 }
console.log(object3)
Codepen:
https://codepen.io/anon/pen/eLxBdK?editors=0001
Use ES6 syntax whenever possible.
shorter code
more readable usually
this case in particular allows you to easily do deep merges (which was a pain before)
faster
Since you are getting the values from a text field, they will initially be JSON strings. In order to treat them like objects and merge then you need to parse them first. Then you can achieve your desired output using jQuery's $.extend() method, which merges one object into another.
Demo:
var obj1 = JSON.parse($("#obj1").val());
var obj2 = JSON.parse($("#obj2").val());
var merged= $.extend({}, obj1, obj2);
console.log(merged);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="obj1" value='{"9":{"322":{"option0":"177"}}}'/>
<input type="text" id="obj2" value='{"10":{"323":{"option":"456"}}}'/>
Documentation: https://api.jquery.com/jquery.extend/
Actually these are objects and not JSON Arrays, and you got an array as result because Array#concat() will return an array and what you want is an object.
So what you can do is to use Object.assign() method:
let obj = Object.assign({}, JSON.parse(o1), JSON.parse(o2));
Note:
If you take these objects from input, you will be getting them as strings you need to parse them with JSON.parse() to getb the right objects.
let o1 = '{"9":{"322":{"option0":"177"}}}';
let o2 = '{"10":{"323":{"option":"456"}}}';
let obj = Object.assign({}, JSON.parse(o1), JSON.parse(o2));
console.log(obj);

Lodash how to assign specific property of object during comparing two collections of different objects

I have one question. Is there any function in lodash library which is going to provide me the method for comparing each object in both collections by specific property and if the condition is fulfilled then creating another object?
example:
a) [{a:1,b:'abc',c:'dfr'},{a:3,b:'dfe',c:'gty'}....{}]
b) [{a:3,b:'fgt',d:'ghr'},{a:5,b:'ghk',d:'bhj'}...{}]
result:[{a:3,b:'dfe',c:'gty',d:'ghr'}]
I would like to compare these two collections by 'a' parameter and if a parameter is matched then assign parameter 'd' to object from the collection a). I have read something about differenceWith or intersection, but I am not sure if it may work, or maybe there are better functions to do this. Thanks in advance!
Create a Map of the items in array2 by their keys. Iterate array1 with Array.filter(), and remove all items that their a property is not found in the Map. Use Array.map() to combine the remaining items with d property of their counterpart in the Map:
const array1 = [{a:1,b:'abc',c:'dfr'},{a:3,b:'dfe',c:'gty'}];
const array2 = [{a:3,b:'fgt',d:'ghr'},{a:5,b:'ghk',d:'bhj'}];
// create a Map of array2 items by the a property
const array2Map = new Map(array2.map((o) => [o.a, o]));
const result = array1
// filter out all items that don't have matching item in the Map
.filter(o => array2Map.has(o.a))
// map the items, and add the d property from the item in the Map
.map(o => ({
...o,
d: array2Map.get(o.a).d
}));
console.log(result);
1) Native way: doing array map and comparing inside map loop with assigning objects.
const array1 = [{a:1,b:'abc',c:'dfr'},{a:3,b:'dfe',c:'gty'}];
const array2 = [{a:3,b:'fgt',d:'ghr'},{a:5,b:'ghk',d:'bhj'}];
const result = array1.map(obj1 => {
const obj2 = array2.find(obj => obj.a === obj1.a);
if (obj2) return Object.assign({}, obj1, {d: obj2.d});
}).filter(value => value);
console.log(result);
2) Lodash way: same as in example 1 but using only lodash methods
const array1 = [{a:1,b:'abc',c:'dfr'},{a:3,b:'dfe',c:'gty'}];
const array2 = [{a:3,b:'fgt',d:'ghr'},{a:5,b:'ghk',d:'bhj'}];
const result = _.compact(
_.map(array1, obj1 => {
const obj2 = _.find(array2, _.matchesProperty('a', obj1.a));
if (obj2) return _.assign({}, obj1, _.pick(obj2, ['d']));
})
);
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.10/lodash.min.js"></script>
P.S. Try to avoid lodash, underscore and etc stuff as much as possible. JS, ES are rich enough.

Why does a js map on an array modify the original array?

I'm quite confused by the behavior of map().
I have an array of objects like this:
const products = [{
...,
'productType' = 'premium',
...
}, ...]
And I'm passing this array to a function that should return the same array but with all product made free:
[{
...,
'productType' = 'free',
...
}, ...]
The function is:
const freeProduct = function(products){
return products.map(x => x.productType = "free")
}
Which returns the following array:
["free", "free", ...]
So I rewrote my function to be:
const freeProduct = function(products){
return products.map(x => {x.productType = "free"; return x})
}
Which returns the array as intended.
BUT ! And that's the moment where I loose my mind, in both cases my original products array is modified.
Documentation around map() says that it shouldn't ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map ).
I even tried to create a clone of my array turning my function into this:
const freeProduct = function(products){
p = products.splice()
return p.map(x => {x.productType = "free"; return x})
}
But I still get the same result (which starts to drive me crazy).
I would be very thankful to anyone who can explain me what I'm doing wrong!
Thank you.
You're not modifying your original array. You're modifying the objects in the array. If you want to avoid mutating the objects in your array, you can use Object.assign to create a new object with the original's properties plus any changes you need:
const freeProduct = function(products) {
return products.map(x => {
return Object.assign({}, x, {
productType: "free"
});
});
};
2018 Edit:
In most browsers you can now use the object spread syntax instead of Object.assign to accomplish this:
const freeProduct = function(products) {
return products.map(x => {
return {
...x,
productType: "free"
};
});
};
To elaborate on SimpleJ's answer - if you were to === the two arrays, you would find that they would not be equal (not same address in memory) confirming that the mapped array is in fact a new array. The issue is that you're returning a new array, that is full of references to the SAME objects in the original array (it's not returning new object literals, it's returning references to the same object). So you need to be creating new objects that are copies of the old objects - ie, w/ the Object.assign example given by SimpleJ.
Unfortunately, whether the spread operator nor the object assign operator does a deep copy.... You need to use a lodash like function to get areal copy not just a reference copy.
const util = require('util');
const print = (...val) => {
console.log(util.inspect(val, false, null, false /* enable colors */));
};
const _ = require('lodash');
const obj1 = {foo:{bar:[{foo:3}]}};
const obj2 = {foo:{bar:[{foo:3}]}};
const array = [obj1, obj2];
const objAssignCopy = x => { return Object.assign({}, x, {})};
const spreadCopy = x => { return {...x}};
const _Copy = x => _.cloneDeep(x);
const map1 = array.map(objAssignCopy);
const map2 = array.map(spreadCopy);
const map3 = array.map(_Copy);
print('map1', map1);
print('map2', map2);
print('map3', map3);
obj2.foo.bar[0].foo = "foobar";
print('map1 after manipulation of obj2', map1); // value changed
print('map2 after manipulation of obj2', map2); // value changed
print('map3 after manipulation of obj2', map3); // value hasn't changed!
Array Iterator Array.map() creates the new array with the same number of elements or does not change the original array. There might be the problem with referencing if there is object inside the array as it copies the same reference, so, when you are making any changes on the property of the object it will change the original value of the element which holds the same reference.
The solution would be to copy the object, well, array.Splice() and [...array](spread Operator) would not help in this case, you can use JavaScript Utility library like Loadash or just use below mention code:
const newList = JSON.parse(JSON.stringify(orinalArr))
Array Destructuring assignment can be used to clone the object.
const freeProduct = function(products){
p = products.splice()
return p.map(({...x}) => {x.productType = "free"; return x})
}
This method will not modify the original object.

Convert Object to 2D array in JavaScript

Can we convert an Object to a 2D Array,
My Object is like this
So That Array Key will be like 'STARS_2' and value is ["STARS_4", "STARS_0", "STARS_12"]
with My attempts I can get something like this,
With this Code,
var testArray =[];
_.map(childFieldNames, function (value, key) {
var newArray = new Array();
newArray[key] = value;
testArray.push(newArray);
});
Here Keys are actually another array, which I do not want. I want key should be like 'STARS_2' , i.e. property of master object.
Is this what you need?
var ary2D = Object.keys(childFieldNames).map(function (key) {
return childFieldNames[key];
});
better version for what Shilly showed would be:
const arr2D = Object.values(childFieldNames);
Object.entries(obj)
E.g.
const objVariable = {name: "Ted", job: "Dentist"}
const 2dArray = Object.entries(objVariable)
console.log(2dArray) // will print [["name", "Ted"], ["job", "Dentist"]]
Object.entries is a static method that belongs to the Object class. As a parameter, it accepts an object and returns a two-dimensional array.
Read more about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
You don’t need to create your structure into 2D array to just iterate over each key and its respective value(which is an array). If you want to iterate over it you can do something like this.
const object = {
a: [1,2,3],
b: [2,3,5]
};
for (const [key, value] of Object.entries(object)) {
value.forEach(v=>{
console.log(`${key}: ${v}`);
})
}

Categories

Resources