Explanation for in loop JavaScript - javascript

Who can explain how this for in loop works and why it's assign keys of object to array
var o = {
a: 1,
b: 2,
c: 3,
d: 4
};
var a = [],
i = 0;
for (a[i++] in o);
console.log(a);

Using a side effect when enumerating the object, and using an empty statement, each key is stored in the array a; first key in a[0], next in a[1] etc.
It is not necessary however since you could just use Object.keys(o)
var o = {
a: 1,
b: 2,
c: 3,
d: 4
};
var a = [],
i = 0;
for (a[i++] in o); // do nothing loop
console.log(a,Object.keys(o));

Related

How can I merge two arrays and make them array of objects in JavaScript

I have a simple question. I have two arrays A and B, I want to return array of object with mixing the two arrays.
For example:
let a = [ 1, 2 ]
let b = [ 3, 4 ]
Expected result:
const C = [
{
a: 1,
b: 3
},
{
a: 2,
b: 4
}
]
How can I do this?
I tried to forloop A then B and assign everytime but it didn't work.
You can use array map method on one of the array and use index to retrieve the element from the second array
let a = [1, 2]
let b = [3, 4];
let c = a.map((item, index) => {
return {
a: item,
b: b[index]
}
});
console.log(c)
Something like this should work:
let a = [1, 2];
let b = [3, 4];
// From #brk. This transforms each element of a to an object containing a's value and b's value
let c = a.map((item, index) => {
a: item,
b: b[index]
});
// Another way. Iterates through each element
for (let i = 0; i < a.length; i++) {
c[i].a = a[i];
c[i].b = b[i];
}
// Yet another. A combination of the first two.
for (let [index, item] of Object.entries(a)) {
c[index] = {
a: item,
b: b[index]
};
}
There's certainly a more elegant solution, but it evades me at the moment

Adding or appending object with object javascript

i am having 2 objects and the code is
Object 1
var existingValue=self.get('objHubDto').ftd.gridDataDTO.gridDTOMap[name].gridDataMap;
Object 2
var newValue = self.get('childDataList')
I need to merge/add/append this two in newvalue value eventhough it having duplicate key values
Following is a very basic example to merge by keeping both values, however, you can create new object rather mutating existing one.
let obj1 = { a: 1, b: 2, c: 3 };
let obj2 = { a: 9, d: 8, e: 7 };
Object.entries(obj2).forEach(([key, val]) => {
obj1[key] = obj1[key] ? [obj1[key], val] : val;
});
console.log(obj1);

Check if array has the key value pairs of the other array

I have two sets of arrays:
var a = [1, 2, {a: 1, b:2}, 3];
var b = [1, {a: 1, b: 2}, 3};
If array a has ALL (EXACT) the properties and values of array b (including objects) then it will increment count by 1. Otherwise, if array a has only some properties and some values doesn't match, it will just exit and do nothing.
As an example:
var a = [1, 2, {a: 1, b:2}, 3];
var b = [1, {a: 1, b: 2}, 3};
// return true / count++
var a = [1, 2, 3, {a: 1, b: 4}];
var b = [1, 2, {a: 1, b: 6}, 3];
return false / no count
Here's my program first:
for(var i = 0; i < mainArr[i]; i++){
if(arr.includes(mainArr[i])){
count++;
}
if(typeof(mainArr[i]) === 'object' && typeof(arr[i]) === 'object'){
for(var mainArrProp in mainArr[i]){
for(var arrProp in arr[i]){
if(arr[i].hasOwnProperty(mainArrProp) && arr[i][arrProp] === mainArr[i][mainArrProp]){
count++;
}
}
}
}
}
Any way to fix this?
If you can use es6, you can leverage some of the new methods to make a (relatively) short function to do this. Specifically we would make use of the array includes, every, and some methods to check for shallow object equality:
function getIncrementValue(set, subset) {
for (let item of subset) {
if (typeof item === "object") {
// Special case if looking at an object. I am assuming object is always shallow.
if (!set.some(otherItem => typeof otherItem === "object" && Object.keys(otherItem).length === Object.keys(item).length && Object.keys(otherItem).every(key => (key in item) && item[key] === otherItem[key]))) return 0;
} else {
if (!set.includes(item)) return 0;
}
}
return 1;
}
// So for your arrays:
var a1 = [1, 2, {a: 1, b:2}, 3];
var b1 = [1, {a: 1, b: 2}, 3];
// return true / count++
var a2 = [1, 2, 3, {a: 1, b: 4}];
var b2 = [1, 2, {a: 1, b: 6}, 3];
// return false / no count
console.log(getIncrementValue(a1, b1)) // returns 1;
console.log(getIncrementValue(a2, b2)) // returns 0;
This is pretty straightforward except for that one long line that checks for object equality. But all that says is:
If there is not some element of set that:
is an object, and
the element and our current item have the same number of keys, and
every key of that element is a key of our current item, and
the values for each key are the same
Then return 1.
You're following totally wrong way, you don't need to work with regular count++ in your case, you should better decrease by one and return, if any value from arrayA doesn't exist in arrayB. I rewrote the method with explanation of each row, I think, it should be clear what's going on. I also noticed, that you write in ES5, but you also use includes(), it's a ES6 feature, good to know. I have left includes() in my implementation too. My method returns 1 if all values from the first array exists in the second, and returns 0 if not. Here it is:
function test(a, b) {
var count = 1,
/* "aValues" will contain both single numbers and object values from "a" array */
aValues = createHomogeneousArray(a),
/* "bValues" will contain both single numbers and object values from "b" array */
bValues = createHomogeneousArray(b);
/* Check does each value of "aValues" exists in "bValues" array, if not - return "count--" (will be equal to "0") */
aValues.forEach(function(item) {
if (!bValues.includes(item)) {
return count--
}
});
/* If nothing was returned yet, return count (is equal to "1") */
return count;
}
function createHomogeneousArray(arr) {
var finalArr = [];
/* Iterate through array */
arr.forEach(function(item) {
/* Check is object */
if (typeof item === 'object') {
/* If object - get all values of this object as array */
var arrOfObjValues = Object.values(item);
/* Iterate through this array with object values */
arrOfObjValues.forEach(function(value) {
/* Push each value of above array to the "finalArr" array, which contains ALL values of the array, passed to this function */
finalArr.push(value);
});
/* Check is number */
} else if (typeof item === 'number') {
/* Push all regular numbers to final array */
finalArr.push(item);
}
});
/* Return "finalArr" array */
return finalArr;
}
console.log(test(
[1, 2, {a: 1, b:2}, 3],
[1, {a: 1, b: 2}, 3]
))
console.log(test(
[1, 2, 3, {a: 1, b: 4}],
[1, 2, {a: 1, b: 6}, 3]
))
Don't be scared of the size of the code, it's much smaller without comments:
function test(a, b) {
var count = 1,
aValues = createHomogeneousArray(a),
bValues = createHomogeneousArray(b);
aValues.forEach(function(item) {
if (!bValues.includes(item)) {
return count--
}
});
return count;
}
function createHomogeneousArray(arr) {
var finalArr = [];
arr.forEach(function(item) {
if (typeof item === 'object') {
var arrOfObjValues = Object.values(item);
arrOfObjValues.forEach(function(value) {
finalArr.push(value);
});
} else if (typeof item === 'number') {
finalArr.push(item);
}
});
return finalArr;
}
console.log(test(
[1, 2, {a: 1, b:2}, 3],
[1, {a: 1, b: 2}, 3]
))
console.log(test(
[1, 2, 3, {a: 1, b: 4}],
[1, 2, {a: 1, b: 6}, 3]
))

JavaScript/Coffeescript sum objects

I would love to "add/merge" (not sure how to call that) some objects in this manner:
obj1 = {
a: 1,
b: 1,
c: 1
}
obj2 = {
a: 1,
b: 1
}
obj1 + obj2 => { a: 2, b: 2, c: 1 }
Is there any way of achieving this? Tried, Object.assign(obj1, obj2) but It will not add properties like I need it to be done (it returns in { a: 1, b: 1, c: 1})
There isn't a built-in way to do it but you can enumerate the properties of one object and add their values to another.
const a = { a: 1, b: 1, c: 1 };
const b = { a: 1, b: 1 };
for(const prop in b) {
a[prop] = (prop in a ? a[prop] : 0) + b[prop];
}
console.log(a);
The prop in a check is so that we don't end up with NaN by adding undefined to the value in b.
You could use reduce to combine n number of objects like so:
const a = { a: 1, b: 1, c: 1 };
const b = { a: 1, b: 1 };
const c = { a: 1, c: 1 };
const result = [a, b, c].reduce((p, c) => {
for(const prop in c) {
p[prop] = (prop in p ? p[prop] : 0) + c[prop];
}
return p;
}, {});
console.log(result);
You didn't mention how you wanted to deal with properties in the prototype chain. You should know that for...in will enumerate properties in the prototype chain and prop in x will also examine the prototype chain. If your only want to enumerate the objects own properties then you could use Object.entries() to get its own properties or do a hasOwnProperty(...) check within the for...in and in place of the prop in x check. If you don't do any prototypal inheritance with your models then you may not care.
A quick answer:
let sum = {};
let keys = new Set(Object.keys(obj1))
Object.keys(obj2).map(x => keys = keys.add(x))
keys.forEach(x => {
let op1 = obj1[x] || 0;
let op2 = obj2[x] || 0;
sum[x] = op1 + op2;
})
Create an empty object:
var obj3 = {};
Use the spread operator to grab all the keys from both objects, then add them to the new object like so:
for(var i in {...obj1, ...obj2}) {
obj3[i] = (obj1[i] || 0) + (obj2[i] || 0);
}
var obj1 = {
a: 1,
b: 1,
c: 1
}
var obj2 = {
a: 1,
b: 2,
d: 3
}
var obj3 = {};
for(var i in {...obj1, ...obj2}) {
obj3[i] = (obj1[i] || 0) + (obj2[i] || 0);
}
console.log(obj3);

How to place each value of an object into an array

I have two objects:
a = {A: 1, B: 2};
a = {C: 3, D: 4};
I need to put the property values of the objects in to one array. So, i'm doing this by iterate each of the objects, but what next, pushing it into one array returns two separated...
$.each(a, function(_key, _val) {
var arr = [];
arr.push(_val);
console.log(arr);
});
How to do this? Is it possible?
I need this: arr = [1, 2, 3, 4];
You are initializing the arr inside the each everytime. Try this:
var arr = [];
$.each(a, function(_key, _val) {
arr.push(_val);
console.log(arr);
});
Here is a fiddle:
https://jsfiddle.net/aarLgmtL/
var a = {A: 1, B: 2};
var b = {C: 3, D: 4};
function join(source, target) {
$.each(source, function(_key, _val) {
target.push(_val);
});
}
var arr = [];
join(a, arr);
join(b, arr);
$("#result").html(JSON.stringify(arr));
You could try using .concat as well. Here is an example from w3schools:
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var children = hege.concat(stale);
http://www.w3schools.com/jsref/jsref_concat_array.asp
Is this what you are looking for?
Don't initialize array in $.each function. It will assign new array every time $.each function call so it end up with last array element in arr variable.
a = {
A: 1,
B: 2
};
b = {
C: 3,
D: 4
};
var arr = [];
function pushToArray(a) {
$.each(a, function(_key, _val) {
arr.push(_val);
});
}
pushToArray(a);
pushToArray(b);
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Make sure that you don't define different object with same name else end up with last object assigned to that variable.
You can simply achieve this by using Object.assign
var a = {A: 1, B: 2};
var b = {C: 3, D: 4};
var copy = Object.assign(a, b);
var result =[];
for(var i in copy){
result.push(copy[i]);
}
console.log(result);
Thanks.
The approach outlined below first creates two separate arrays, one from a and one from b, and then concatenates them together (with a little help from the jQuery Array#map method.)
a = {A: 1, B: 2};
b = {C: 3, D: 4};
var arrayFromA = $.map(a, function(value, index) {
return [value];
});
var arrayFromB = $.map(b, function(value, index) {
return [value];
});
finalArray = arrayFromB.concat(arrayFromA);

Categories