editing JavaScript object - javascript

I have this object:
obj = {key : val,
key1 : val1,
key2 : {key21 : val21,key22 : val22},
key3 : val3}
I want to generate a new object to be like:
objnew = {key : val,
key1 : val1,
key21 : val21,
key22 : val22,
key3 : val3}

As per your comments, if you really want to keep the order for whatever reason, and don't want to do it for anything but key2, here's a possible solution.
Please read this question for information about order of object keys. In short, it's most likely a bad idea to rely on it in most cases. You'd be better off using a Map instance or just an array.
let obj = {
key: 0,
key1: 1,
key2: {key21: 21, key22: 22},
key3: 3
};
let objArray = Object.keys(obj).map(key => ({key, value: obj[key]}));
let result = objArray.reduce((result, entry) =>
Object.assign(result, entry.key === 'key2' ? entry.value : {[entry.key]: entry.value})
, {});
console.log(result);

For 2-level object structure (with Object.keys() and Object.assign() functions):
var obj = {
'key' : 'val',
'key1' : 'val1',
'key2' : {'key21' : 'val21', 'key22' : 'val22'},
'key3' : 'val3'
};
Object.keys(obj).forEach(function(k){
if (typeof obj[k] === 'object') {
Object.assign(obj, obj[k]);
delete obj[k];
}
});
console.log(obj);

Here you go:
var obj = {
key : 1,
key1 : 2,
key2 : { key21 : 3,key22 : 4 },
key3 : 5
};
Object.keys(obj).forEach(function(key) {
if(typeof obj[key] === 'object') {
Object.keys(obj[key]).forEach(function(innerKey) {
obj[innerKey] = obj[key][innerKey];
});
delete obj[key];
}
});
console.log(obj);

Related

How to get unique values from an array of JS objects?

I need some help figuring out how to get unique values from an array of objects in this format. I have reviewed several examples but none had the values of a key being an array. Thanks in advance for your advice.
I have a JS array with complex objects with some object values being arrays:
let array = [
{ key1: ["one","two","four"], key2: [1,2,4] },
{ key1: ["two","four","six"], key2: [2,4,6] },
{ key1: "nine", key2: 9 },
];
I want to get the unique values for all keys in the object (so it will support any structure) and output like this:
[
{
key1: ["one","two","four", "six", "nine"],
key2: [1,2,4,6,9]
}
]
You can try this :
let array = [
{ key1: ["one","two","four"], key2: [1,2,4] },
{ key1: ["two","four","six"], key2: [2,4,6] },
{ key1: "nine", key2: 9 },
];
let keys = [...new Set(array.flatMap(d => Object.keys(d)))];
let valuesAsObj = Object.fromEntries(
keys.map(k => [
k,
[... new Set(array.flatMap(d => d[k] ? d[k] : null).filter(v => v != null && v != undefined))]
])
);
let valuesAsArr = keys.map(k => [... new Set(array.flatMap(d => d[k] ? d[k] : null).filter(v => v != null && v != undefined))])
console.log(valuesAsObj);
console.log(valuesAsArr);
I approached it by creating a Set for each unique property and adding all the properties to that set.
let array = [
{ key1: ["one","two","four"], key2: [1,2,4] },
{ key1: ["two","four","six"], key2: [2,4,6] },
{ key1: "nine", key2: 9 },
];
const result = {};
array.forEach(a => {
for (let key in a) {
if (!result[key]) result[key] = new Set();
let v = a[key];
if (!Array.isArray(v)) v = [v];
v.forEach(result[key].add, result[key]);
}
});
console.log(result );
const overlyComplicatedResult = Object.entries(result).map(([key,val]) => ({[key]: [...val]}));
console.log(overlyComplicatedResult);
I'm personally happy with the results in the intermediate format that they are stored in the result variable, which is just a single object where each property is one of the keys and the value of each property is a Set of all the distinct values.
But, if you really want to transform that into your overly complicated result, where you have an array of objects, each with a single property, and the unique items are stored in an array instead of a Set, then the code is provided above as a final transformation step using Object.entries.
You could try something like this:
let array = [
{ key1: ["one","two","four"], key2: [1,2,4] },
{ key1: ["two","four","six"], key2: [2,4,6] },
{ key1: "nine", key2: 9 },
];
let obj = {};
array.forEach((item) =>
Object.entries(item).forEach((entry) => {
if (!obj[entry[0]]) obj[entry[0]] = [];
!Array.isArray(entry[1])
? obj[entry[0]].push(entry[1])
: (obj[entry[0]] = [...obj[entry[0]], ...entry[1]]);
})
);
/*ADDED LOGIC TO HAVE UNIQUE VALUES IN THE OBJECT*/
Object.entries(obj).forEach(
(entry) => (obj[entry[0]] = Array.from(new Set(entry[1])))
);
console.log(obj);
let result = [];
Object.entries(obj).forEach((entry) =>
result.push({
[entry[0]]: Array.from(new Set(entry[1])),
})
);
console.log(result);

Comparing two nested JSON structures

I'm trying to compare two JSON structures by their keys, not the values inside the keys.
The goal is to see if the one is different by the other. I don't need a diff, just a simple flag. I've tried to do it but somehow I can't get a solution that would not be overcomplicated.
Sample JSON1 structure
{ "parentKey" :
{ "childKey" : { "nestedKey" : "value" },
"childKey2: "value2" }}
JSON2
{ "parentKey" :
{ "childKey" : { "nestedKey" : "value2",
"nestedKey2": "value3"},
"childKey2: "value2" }}
If you only need to see if the 2 objects are not exactly identical (just the keys, not the values) It's pretty simple, you just check Every key in both objects. If you need to know what key is different or how is different it's entirely a different problem.
let o1 = { "parentKey" :
{ "childKey" : { "nestedKey" : "value" },
"childKey2": "value2" }}
let o2 = { "parentKey" :
{ "childKey" : { "nestedKey" : "value2",
"nestedKey2": "value3"},
"childKey2": "value2" }}
let keysInObj1 = []
let keysInObj2 = []
function compare(object, arr){
for (const obj in object){
arr.push(obj)
if(typeof(object[obj]) == 'object'){
compare(object[obj], arr)
}
}
}
compare(o1, keysInObj1)
compare(o2, keysInObj2)
keysInObj1.forEach((val, index)=>{
if(keysInObj2[index] != val){
console.log('Objects are not the same')
}
})
JsFiddle
Here is an iterative solution using object-scan
This solution could easily be modified to tell you exactly the keys that the objects are different.
// const objectScan = require('object-scan');
const d1 = { parentKey: { childKey: { nestedKey: 'value' }, childKey2: 'value2' } };
const d2 = { parentKey: { childKey: { nestedKey: 'value2', nestedKey2: 'value3' }, childKey2: 'value2' } };
const cmp = (a, b) => {
const r1 = objectScan(['**'], { joined: true })(a);
const r2 = objectScan(['**'], { joined: true })(b);
if (r1.length !== r2.length) {
return false;
}
return r1.every((e) => r2.includes(e));
};
console.log(cmp(d1, d2));
// => false
console.log(cmp(d1, d1));
// => true
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#14.3.1"></script>
Disclaimer: I'm the author of object-scan
const compareKeys = (obj1, obj2) =>
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every((key) => key in obj2);
var object1 = {
"banana": "bar",
"orange": "foo"
};
var object2 = {
"banana": "foo",
"orange": "bar"
};
var object3 = {
"aaaaa": "bar",
"jjjjj": "foo"
};
//Expected output: true
console.log(compareKeys(object1, object2));
//Expected output: false
console.log(compareKeys(object1, object3));
I have tried this approach keep in mind the structure should be same too.
Therefore,
{name: "Anuj", isTaxPayer: true}
{isTaxPayer: true, name: "Shonster"}
will not be same
var keys1 = [];
var keys2 = [];
var json1 = { "parentKey" :
{ "childKey" : { "nestedKey" : "value" },
"childKey2": "value2" }};
var json2 = { "parentKey" :
{ "childKey" : { "nestedKey" : "value2",
"nestedKey2": "value3"},
"childKey2": "value2" }};
function getKeys(Obj, res){
res === undefined ? res = [] : 1;
for(prop in Obj){
res.push(prop);
if(Object.prototype.toString.call(Obj[prop]).match(/\s([a-zA-Z]+)/)[1] === "Object"){
getKeys(Obj[prop], res);
}
}
return res;
}
function isDifferent(){
keys1 = getKeys(json1).join("").toLowerCase();
keys2 = getKeys(json2).join("").toLowerCase();
keys1 === keys2 ? alert("SAME") : alert("NOPE");
}
isDifferent();

Get only object key values which have non blank using lodash

I have an array which has specific keys of an object obj
arr_keys = ['key1','key4','key5'];
And I also have an object with key value pair as below
obj = { 'key1' : '', 'key2' : 'val2', 'key3' : '', 'key4' : 'val4', 'key5' : '' };
Now I am looking for some function in lodash which could give me x object filtered from obj object as
x = _.someFunc(obj,arr_keys)
// x = { 'key4' : 'val4' }
We can see that I have only got key value pair of 'key4' : 'val4' and ommited
keys 'key1' and 'key5' as they had blank values
It's very easy just try this fn
let arr_keys = ['key1', 'key4', 'key5'];
let obj = { 'key1': '', 'key2': 'val2', 'key3': '', 'key4': 'val4', 'key5': '' };
function someFunc(obj, arr_keys) {
let resultObj = {};
arr_keys.forEach((element) => {
if (obj[element])
resultObj[element] = obj[element];
})
return resultObj;
}
console.log(someFunc(obj,arr_keys))
so the result will be { 'key4' : 'val4' }
You could chain pickBy and identity to get properties where value is not empty string or undefined and then use pick method to get only properties where key is in array.
const arr = ['key1','key4','key5'];
const obj = { 'key1' : '', 'key2' : 'val2', 'key3' : '', 'key4' : 'val4', 'key5' : '' };
const result = _(obj).pickBy(_.identity).pick(arr).value()
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Use lodash's _.pickBy() to get an object from another object using a list of keys and another condition (v not blank):
const arr_keys = ['key1','key4','key5'];
const obj = { 'key1' : '', 'key2' : 'val2', 'key3' : '', 'key4' : 'val4', 'key5' : '' };
const result = _.pickBy(obj, (v, k) => v && arr_keys.includes(k));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
With vanilla JS you can convert to pairs using Object.entries(), filter the array of pairs, and then use Object.entries() to convert back to an object:
const arr_keys = ['key1','key4','key5'];
const obj = { 'key1' : '', 'key2' : 'val2', 'key3' : '', 'key4' : 'val4', 'key5' : '' };
const result = Object.fromEntries(
Object.entries(obj)
.filter(([k, v]) => v && arr_keys.includes(k))
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

JavaScript Deleting all objects from an array which contain a value

I have an obj, with an array of objects - something like below (I've not pasted it here because its HUGE). I'm trying to loop through the array of objects - deleting those objects from the array which contain a value. I have written the following code... (using lodash)
When looping over the array its randomly missing a few 'Foo's - so not all the Foo objects are deleted... even though they contain the key Foo. It does ignore that which doesn't contain Foo though.
obj = {
array : [
{
key1 : 'Foo',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi',
Key3 : 'blah'
},
{
key1 : 'Fred',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi'
}
... etc....
]
}
var items = obj.array
_.forEach(items, function(n, index) {
var isFoo = _.includes(n, 'Foo');
console.log(isFoo);
if (isFoo) {
items.splice(index, 1);
}
});
I suspect things are getting confused because you are changing the array at the same time as you are looping through it.
_.remove is probably a better option for you here:
var obj = {
array : [
{
key1 : 'Foo',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi',
Key3 : 'blah'
},
{
key1 : 'Fred',
Key2 : 'fi'
},
{
key1 : 'Foo',
Key2 : 'fi'
}
]
};
_.remove(obj.array, function(n, index) {
return _.includes(n, 'Foo');
});
console.dir(obj.array)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.js"></script>
I ditched lodash, and just did a reverse for-loop (my thinking was that as things were being removed, the index would change... and maybe that was causing the errors?)
var items = obj.array;
var i;
for (i = items.length - 1; i >= 0; i -= 1) {
if (items[i].type === 'Foo') {
items.splice(i, 1);
}
}

Getting JavaScript object key list

I have a JavaScript object like
var obj = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
key4: 'value4'
}
How can I get the length and list of keys in this object?
var obj = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
key4: 'value4'
}
var keys = Object.keys(obj);
console.log('obj contains ' + keys.length + ' keys: '+ keys);
It's supported on most major browsers now.
var obj = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
key4: 'value4'
};
var keys = [];
for (var k in obj) keys.push(k);
console.log("total " + keys.length + " keys: " + keys);
Underscore.js makes the transformation pretty clean:
var keys = _.map(x, function(v, k) { return k; });
Edit: I missed that you can do this too:
var keys = _.keys(x);
If you only want the keys which are specific to that particular object and not any derived prototype properties:
function getKeys(obj) {
var r = []
for (var k in obj) {
if (!obj.hasOwnProperty(k))
continue
r.push(k)
}
return r
}
e.g:
var keys = getKeys({'eggs': null, 'spam': true})
var length = keys.length // access the `length` property as usual for arrays
var keys = new Array();
for(var key in obj)
{
keys[keys.length] = key;
}
var keyLength = keys.length;
to access any value from the object, you can use obj[key];
obj = {'a':'c','b':'d'}
You can try:
[index for (index in obj)]
this will return:
['a','b']
to get the list of keys
or
[obj[index] for (index in obj)]
to get the values
Anurags answer is basically correct.
But to support Object.keys(obj) in older browsers as well you can use the code below that is copied from
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
. It adds the Object.keys(obj) method if it's not available from the browser.
if (!Object.keys) {
Object.keys = (function() {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function(obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
Use Object.keys()... it's the way to go.
Full documentation is available on the MDN site linked below:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Note that in coffeescript this can be accomplished in all browsers and node as
k for k of obj
and thus
(1 for _ of obj).length
Recursive solution for browsers that support ECMAScript 5:
var getObjectKeys = function(obj) {
var keys = Object.keys(obj);
var length = keys.length;
if (length !== 0) {
for (var i = 0; i < length; i++) {
if (typeof obj[keys[i]] === 'object') {
keys[keys[i]] = getObjectKeys(obj[keys[i]]);
}
}
}
return keys;
};
var obj = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
key4: 'value4'
}
console.log(Object.keys(obj));
console.log(Object.keys(obj).length)
If you decide to use Underscore.js you better do
var obj = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
key4: 'value4'
}
var keys = [];
_.each( obj, function( val, key ) {
keys.push(key);
});
console.log(keys.lenth, keys);
In JavaScript, an object is a standalone entity, with properties and type.
For fetching values from Object in form of array:
Object.values(obj) // obj is object name that you used
Result -> ["value1", "value2", "value3", "value4"]
For fetching keys from Object in form of array:
Object.keys(obj) // obj is object name that you used
Result -> ["key1", "key2", "key3", "key4"]
As both functions are returning array you can get the length of keys or value by using length property. For instance - Object.values(obj).length or Object.keys(obj).length
Modern browsers do support:
var obj = {
key1: 'value1',
key2: 'value2',
key3: 'value3',
key4: 'value4'
}
console.log(Object.keys(obj));
// we can also get values
console.log(Object.values(obj));
For a comma-delineated string listing the keys of a JSON Object, try the following:
function listKeys(jObj){
var keyString = '';
for(var k in jObj){
keyString+=(','+k);
}
return keyString.slice(1);
}
/* listKeys({'a' : 'foo', 'b' : 'foo', 'c' : 'foo'}) -> 'a,b,c' */
Using ES6,
you can use forEach to iterate over the Keys of an Object.
To get all the keys you can use Object.keys which returns all the keys in an Object
Object.keys(obj).forEach(function(keyValue, index, map) {
console.log(keyValue);
});
Short hand of the above snippet would be, which only takes one parameter
Object.keys(obj).forEach(function(keyValue) {
console.log(keyValue);
});
if(props.userType){
var data = []
Object.keys(props.userType).map(i=>{
data.push(props.userType[i])
})
setService(data)
}
using slice, apply and join method.
var print = Array.prototype.slice.apply( obj );
alert('length='+print.length+' list'+print.join());
Here is solution for getting all the keys from an nested object/array.
It will recursively check for the object inside an array.
function Keys() {
let keys = [];
this.pushKey = function (key) {
keys.push(key);
};
this.getKeys = function () {
return keys;
};
}
let keys = new Keys();
let arr = [
{
a: 1,
b: {
c: [{ d: 1, e: [{ f: 1 }] }],
},
},
{
g: 1,
h: {
i: [{ j: 1, k: [{ l: 1 }] }],
},
},
];
function getObject(arr) {
for (let item of arr) {
if (Array.isArray(item)) getObject(item);
else getKeys(item);
}
}
function getKeys(obj) {
for (let key in obj) {
if (Array.isArray(obj[key])) getObject(obj[key]);
else if (typeof obj[key] === "object") getKeys(obj[key]);
keys.pushKey(key);
}
}
getObject(arr);
console.log(keys.getKeys());

Categories