Get only object key values which have non blank using lodash - javascript

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>

Related

How to use spread operator but not get values null from the object

I have an array of object, something like this:
array = [
{
'propertyName1': 'name1',
'propertyValue1': 'value1',
'propertyName2': 'name2',
'propertyValue2': 'value2',
'propertyName3': 'name3',
'propertyValue3': 'value3',
'propertyName4': 'name4',
'propertyValue4': 'value4',
},
{
'propertyName1': 'name10',
'propertyValue1': 'value10',
'propertyName2': 'name22',
'propertyValue2': 'value22',
'propertyName3': 'name33',
'propertyValue3': 'value33',
'propertyName4': null,
'propertyValue4': null,
}
]
I want to get the first value as a key and the second value as a value in a new object, something like this result:
{
name1: "value1"
name10: "value10"
name2: "value2"
name22: "value22"
name3: "value3"
name33: "value33"
name4: "value4"
null: null
}
but I don't want to show the property with the value null, so I tried:
ngOnInit() {
let obj = {};
this.array.forEach((element: any) => {
obj = {
...obj,
[element.propertyName1]: element.propertyValue1,
[element.propertyName2]: element.propertyValue2,
[element.propertyName3]: element.propertyValue3,
[element.propertyName4]: element.propertyValue4}
}
);
console.log(obj);
}
See the code here:
Stackblitz
Just delete the null entry after
this.array.forEach((element: any) => {
obj = {
...obj,
[element.propertyName1]: element.propertyValue1,
[element.propertyName2]: element.propertyValue2,
[element.propertyName3]: element.propertyValue3,
[element.propertyName4]: element.propertyValue4,
};
});
delete obj['null'];
https://stackblitz.com/edit/angular-ivy-gaqes8?file=src/app/app.component.ts
You can spread all the values in a single array and check if the property is null while looping over:
ngOnInit() {
const valuesArray = [ //Array containing all the values
...Object.values(this.array[0]),
...Object.values(this.array[1]),
];
let obj = {};
for (let i = 0; i < valuesArray.length; i = i + 2) {
if (valuesArray[i + 1] !== null) {
obj[valuesArray[i]] = valuesArray[i + 1]; //Only copy when it is not null
}
}
console.log(obj);
}
If your first array also might contain null values and you want to exclude them you can use this if condition instead of the one above:
if (valuesArray[i + 1] !== null && valuesArray[i] !== null )
const data = [{"propertyName1":"name1","propertyValue1":"value1","propertyName2":"name2","propertyValue2":"value2","propertyName3":"name3","propertyValue3":"value3","propertyName4":"name4","propertyValue4":"value4"},{"propertyName1":"name10","propertyValue1":"value10","propertyName2":"name22","propertyValue2":"value22","propertyName3":"name33","propertyValue3":"value33","propertyName4":null,"propertyValue4":null}]
let r = {}
// get maximum number of keys that may need to be iterated over
let n = data.map(o=>Object.keys(o).length).reduce((a,c)=>Math.max(a,c))
for(let i=1; i<=n; i++) {
data.forEach(o=> {
let x = o[`propertyName${i}`]
let y = o[`propertyValue${i}`]
if (x && y) r[x] = y
})
}
console.log(r)

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);

Get value by key from array of array - Javascript

I have a meta as below:
obj = {
meta: [['type', 'test1'], ['key2', 'value2']],
value: 'text1',
}
Want to read value test by passing the key type
expected result is test1
You could use Object.fromEntries()
const obj = {
meta: [['type', 'test'], ['key2', 'value2']],
value: 'text1',
}
const key = 'type'
const res = Object.fromEntries(obj.meta)[key];
console.log(res)
You should restructure meta as an object instead of an array of pairs as:
obj = {
meta: {
'type': 'test',
'key2': 'value2'
}
value: 'text1',
}
Now, you can access what you need as obj['meta']['type'] or obj.meta.type.
obj = {
meta: [['type', 'test'], ['key2', 'value2']],
value: 'text1',
}
for(let arr of obj.meta){
if(arr[0]==='type'){
return arr[1];
}
}
or
const res=obj.meta.find(arr=>arr[0]==="type");
if(res && res.length) return res[1]
Notice that this code returns only the first "type". If you have "type" twice you'll get the first 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();

editing JavaScript object

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);

Categories