How do we check the keys and compare it to the data object , if one or more keys from the keys array does not exist in object data or if it exist or key exists and the key value has no value or null or undefined then return false else return true.
For example keys has a key summary and it exists on object data but the value is empty so it should return false;
I've tried Object.keys and used includes but cant seem to work it out, maybe someone has an idea. Thanks.
#currentCode
const sample = Object.entries(sampleOject).some((value) => {
return keys.includes(value[0]) ? false : (value[1] === null || value[1] === "");
})
Thanks.
#keys
const keys = [
'summary',
'targetRecdate',
'majorPositiveAttributes',
'generalRealEstateConcernsorChallenges',
'terminationPayment',
'effectiveDate',
'brokerCommission',
'brokerRebate',
'netEffectiveBrokerCommission']
#sample object data
{
"dealDispositionType": "A",
"majorPositiveAttributes": "a",
"terminationPayment": "31",
"netEffectiveBrokerCommission": -12189,
"brokerCommission": "123",
"brokerRebate": "12312",
"isPharmacyRestriction": 0,
"periodOfRestriction": null,
"pharmacyRestrictionDate": null,
"targetRecdate": "2022-10-20",
"isLandLordConsent": false,
"summary: ""
}
You could use every() with hasOwnProperty and additional checks for empty strings etc
const result = keys.every(key => {
return data.hasOwnProperty(key) && data[key] !== ''
}, {});
const keys = [
'summary',
'targetRecdate',
'majorPositiveAttributes',
'generalRealEstateConcernsorChallenges',
'terminationPayment',
'effectiveDate',
'brokerCommission',
'brokerRebate',
'netEffectiveBrokerCommission'
];
const data = {
"dealDispositionType": "A",
"majorPositiveAttributes": "a",
"terminationPayment": "31",
"netEffectiveBrokerCommission": -12189,
"brokerCommission": "123",
"brokerRebate": "12312",
"isPharmacyRestriction": 0,
"periodOfRestriction": null,
"pharmacyRestrictionDate": null,
"targetRecdate": "2022-10-20",
"isLandLordConsent": false,
"summary": ""
};
const result = keys.every(key => {
return data.hasOwnProperty(key) && data[key] !== ''
}, {});
console.log(result); // False
I just optimized your code.
const sample = Object.entries(sampleOject).map(([key, value]) => {
return keys.includes(key) ? value ? true : false : false;
})
...
const keys = [
'summary',
'targetRecdate',
'majorPositiveAttributes',
'generalRealEstateConcernsorChallenges',
'terminationPayment',
'effectiveDate',
'brokerCommission',
'brokerRebate',
'netEffectiveBrokerCommission']
const obj = {
"dealDispositionType": "A",
"majorPositiveAttributes": "a",
"terminationPayment": "31",
"netEffectiveBrokerCommission": -12189,
"brokerCommission": "123",
"brokerRebate": "12312",
"isPharmacyRestriction": 0,
"periodOfRestriction": null,
"pharmacyRestrictionDate": null,
"targetRecdate": "2022-10-20",
"isLandLordConsent": false,
"summary": "test"
}
let arr = [];
const result = Object.entries(obj).map(([key, val]) => {
if (keys.includes(key)) {
if ((val !== '') && (val !== 'undefined') && (val !== 'null') ) {
return true;
} else {
return false;
}
} else {
return false;
}
})
const getValue = result.includes(true);
console.log(getValue)
My approach would be to check whether all keys are present in data with the help of .every.
Also non-strict != will check if certain key contain neither null nor undefined
const keys = [
'summary',
'targetRecdate',
'majorPositiveAttributes',
'generalRealEstateConcernsorChallenges',
'terminationPayment',
'effectiveDate',
'brokerCommission',
'brokerRebate',
'netEffectiveBrokerCommission'];
const data = {
"dealDispositionType": "A",
"majorPositiveAttributes": "a",
"terminationPayment": "31",
"netEffectiveBrokerCommission": -12189,
"brokerCommission": "123",
"brokerRebate": "12312",
"isPharmacyRestriction": 0,
"periodOfRestriction": null,
"pharmacyRestrictionDate": null,
"targetRecdate": "2022-10-20",
"isLandLordConsent": false,
"summary": ""
};
const check = (obj, keys) => keys.every((key) =>
key in obj && obj[key] != undefined);
console.log(check(data, keys));
According to mdn,
const car = { make: 'Honda', model: 'Accord', year: 1998 };
console.log('make' in car); // output: true
Related
I need to convert object:
{
middleName: null,
name: "Test Name",
university: {
country: {
code: "PL"
},
isGraduated: true,
speciality: "Computer Science"
}
}
to array:
[{
key: "name",
propertyValue: "Test Name",
},
{
key: "middleName",
propertyValue: null,
},
{
key: "university.isGraduated",
propertyValue: true,
},
{
key: "university.speciality",
propertyValue: "Computer Science",
},
{
key: "university.country.code",
propertyValue: "PL"
}];
I wrote algorithm, but it's pretty dummy, how can I improve it? Important, if object has nested object than I need to write nested object via dot (e.g university.contry: "value")
let arr = [];
Object.keys(parsedObj).map((key) => {
if (parsedObj[key] instanceof Object) {
Object.keys(parsedObj[key]).map((keyNested) => {
if (parsedObj[key][keyNested] instanceof Object) {
Object.keys(parsedObj[key][keyNested]).map((keyNestedNested) => {
arr.push({ 'key': key + '.' + keyNested + '.' + keyNestedNested, 'propertyValue': parsedObj[key][keyNested][keyNestedNested] })
})
} else {
arr.push({ 'key': key + '.' + keyNested, 'propertyValue': parsedObj[key][keyNested] })
}
})
} else {
arr.push({ 'key': key, 'propertyValue': parsedObj[key] })
}
});
Thanks
A recursive function implementation.
I have considered that your object consist of only string and object as the values. If you have more kind of data types as your values, you may have to develop on top of this function.
const myObj = {
middleName: null,
name: "Test Name",
university: {
country: {
code: "PL"
},
isGraduated: true,
speciality: "Computer Science"
}
}
const myArr = [];
function convertObjectToArray(obj, keyPrepender) {
Object.entries(obj).forEach(([key, propertyValue]) => {
if (typeof propertyValue === "object" && propertyValue) {
const updatedKey = keyPrepender ? `${keyPrepender}.${key}` : key;
convertObjectToArray(propertyValue, updatedKey)
} else {
myArr.push({
key: keyPrepender ? `${keyPrepender}.${key}` : key,
propertyValue
})
}
})
}
convertObjectToArray(myObj);
console.log(myArr);
I'd probably take a recursive approach, and I'd probably avoid unnecessary intermediary arrays (though unless the original object is massive, it doesn't matter). For instance (see comments):
function convert(obj, target = [], prefix = "") {
// Loop through the object keys
for (const key in obj) {
// Only handle "own" properties
if (Object.hasOwn(obj, key)) {
const value = obj[key];
// Get the full key for this property, including prefix
const fullKey = prefix ? prefix + "." + key : key;
if (value && typeof value === "object") {
// It's an object...
if (Array.isArray(value)) {
throw new Error(`Arrays are not valid`);
} else {
// ...recurse, providing the key as the prefix
convert(value, target, fullKey);
}
} else {
// Not an object, push it to the array
target.push({key: fullKey, propertyValue: value});
}
}
}
// Return the result
return target;
}
Live Example:
const original = {
middleName: null,
name: "Test Name",
university: {
country: {
code: "PL"
},
isGraduated: true,
speciality: "Computer Science"
}
};
function convert(obj, target = [], prefix = "") {
// Loop through the object keys
for (const key in obj) {
// Only handle "own" properties
if (Object.hasOwn(obj, key)) {
const value = obj[key];
// Get the full key for this property, including prefix
const fullKey = prefix ? prefix + "." + key : key;
if (value && typeof value === "object") {
// It's an object...
if (Array.isArray(value)) {
throw new Error(`Arrays are not valid`);
} else {
// ...recurse, providing the key as the prefix
convert(value, target, fullKey);
}
} else {
// Not an object, push it to the array
target.push({key: fullKey, propertyValue: value});
}
}
}
// Return the result
return target;
}
const result = convert(original, []);
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}
Note that I've assumed the order of the array entries isn't significant. The output you said you wanted is at odds with the standard order of JavaScript object properties (yes, they have an order now; no, it's not something I suggest relying on 😀). I've gone ahead and not worried about the order within an object.
This is the most bulletproof I could do :D, without needing a global variable, you just take it, and us it wherever you want!
const test = {
middleName: null,
name: "Test Name",
university: {
country: {
code: "PL"
},
isGraduated: true,
speciality: "Computer Science"
}
};
function toPropertiesByPath(inputObj) {
let arr = [];
let initialObj = {};
const getKeys = (obj, parentK='') => {
initialObj = arr.length === 0 ? obj: initialObj;
const entries = Object.entries(obj);
for(let i=0; i<entries.length; i++) {
const key = entries[i][0];
const val = entries[i][1];
const isRootElement = initialObj.hasOwnProperty(key);
parentK = isRootElement ? key: parentK+'.'+key;
if(typeof val === 'object' && val!==null && !Array.isArray(val)){
getKeys(val, parentK);
} else {
arr.push({ key: parentK, property: val });
}
}
};
getKeys(inputObj);
return arr;
}
console.log(toPropertiesByPath(test));
I wrote a small version using recursive function and another for validation is an object.
let values = {
middleName: null,
name: "Test Name",
university: {
country: {
code: "PL"
},
isGraduated: true,
speciality: "Computer Science"
}
}
function isObject(obj) {
return obj != null && obj.constructor.name === "Object"
}
function getValues(values) {
let arrValues = Object.keys(values).map(
v => {
return { key: v, value: isObject(values[v]) ? getValues(values[v]) : values[v] };
});
console.log(arrValues);
}
getValues(values);
i have dynamic generated list of checkbox, i want to create array with objects.
I wanted to push data in array of objects if value is true and setItem to localStorage,
and if value is false then it will remove objects from local storage
Can anyone help me to optmize my code with expected output.
Expected output
[
{
"key": "Test",
"value": true
},
{
"key": "Test1",
"value": true
},
{
"key": "removeItem",
"value": false
}
]
Code
setColumn($event, item) {
var obj = {}, valueAliasPair = [];
if (item.tabelHeader.data != '' && $event.checked === true) {
obj['key'] = item.tabelHeader.data;
obj['value'] = $event.checked;
valueAliasPair.push(obj);
localStorage.setItem('AvailableAmt', JSON.stringify(valueAliasPair));
}
if (item.tabelHeader.data != '' && $event.checked === false) {
localStorage.removeItem('AvailableAmt', obj['key']);
}
console.log(valueAliasPair, "valueAliasPair");
}
Updated:
setColumn($event, item) {
let valueAliasPair = JSON.parse(localStorage.getItem("AvailableAmt") || "[]");
if (item.tabelHeader.data != "") {
if ($event.checked) {
valueAliasPair.push({
key: item.tabelHeader.data,
value: true,
});
localStorage.setItem("AvailableAmt", JSON.stringify(valueAliasPair));
} else {
const ind = valueAliasPair.findIndex((x) => x.key === item.tabelHeader.data);
valueAliasPair.splice(ind, 1);
localStorage.setItem("AvailableAmt", JSON.stringify(valueAliasPair));
}
}
console.log(valueAliasPair, "valueAliasPair");
}
I have next array of objects:
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
What I need is to filter out elements which is empty, null or undefined and convert it to one object pameters:
{
givenName: 'firstName',
familyName: 'lastName',
'custom:data': 'blabla'
}
You could filter the array by looking to the values. This approach assumes, that only one key/value pair is available.
const
fields = [{ givenName: 'firstName' }, { familyName: 'lastName' }, { 'custom:data': 'blabla' }, { 'custom:data2': '' }, { 'custom:data3': null }],
result = Object.assign({}, ...fields.filter(o => {
const [v] = Object.values(o);
return v || v === 0 || v === false;
}));
console.log(result);
How to check whether a value is empty?
Most people would go about this with a truthy check:
const empty = x => x ? false : true;
empty(null); //=> true
empty(undefined); //=> true
empty(''); //=> true
But that's always going to exclude things you perhaps didn't intend to exclude:
empty(0); //=> true
empty(false); //=> true
empty(NaN); //=> true
Admittedly NaN could be seen as the "empty" value of its type but for the sake of your question and educational purpose we'll say it's not.
The "workaround" is often something like that:
const empty = x => (x || x === 0 || x === false || Number.isNaN(x)) ? false : true;
However this doesn't need to be more complicated than this:
const empty = x => x == null || x === '' ? true : false;
Checking for either undefined or null is one example where not using triple equality makes sense:
null == undefined;
// true
null === undefined;
// false
See Google JavaScript Style Guide.
If you need to exclude null, undefined and '' please don't rely on clever shorthand tricks and just be explicit about it. Type checking should be a straightforward job (YMMV) and not a show-off contest. Future you and your team mates will thank you.
As for your question, I'd suggest this:
Merge everything you've got with Object.assign:
Object.assign({}, {a:1}, {b:2}, {c:2});
// {a: 1, b: 2, c: 3}
Then deconstruct it into pairs, exclude those whose value is empty, then reconstruct the object from what's left:
const merge = xs =>
Object.fromEntries(
Object.entries(
Object.assign({}, ...xs))
.filter(([_, v]) =>
v != null && v !== ''));
console.log(merge(fields));
<script>
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
</script>
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
res = fields.reduce((acc, cur) => {
if (cur[Object.keys(cur)[0]]) {
acc = { ...acc, ...cur }
}
return acc
}, {})
console.log(res)
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
const result = fields.reduce( ( acc, field ) => {
Object.keys( field ).forEach( ( key ) => {
if( field[key] ) {
acc[key] = field[key];
}
} )
return acc;
}, {} )
console.log(result)
You could use reduce and forEach and check if value of each property is falsy or not.
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
const result = fields.reduce((r, e) => {
Object.entries(e).forEach(([k, v]) => {
if (v || [false, 0].includes(v)) r[k] = v
})
return r
}, {})
console.log(result)
Use Array.prototype.filter() method to filter out the empty, null or undefined objects. Then using Array.prototype.map() make a key-value pair array. At last, use Object.fromEntries() method to transform it to a single object.
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
const ret = Object.fromEntries(
fields
.filter((x) => {
const value = Object.values(x)[0];
return value || value === false || value === 0 || Object.is(value, NaN);
})
.map((x) => [Object.keys(x)[0], Object.values(x)[0]])
);
console.log(ret);
It might help you.
const fields = [
{ givenName: 'firstName' },
{ familyName: 'lastName' },
{ 'custom:data': 'blabla' },
{ 'custom:data2': '' },
{ 'custom:data3': null },
];
let item = {};
for ( let i = 0; i < fields.length; i++ ){
for (const [key, value] of Object.entries(fields[i])) {
if ( value !== null && value !== '' )
item [key] = value;
}
}
console.log(item);
Works with one key, simple modification can work on n keys.
const fields = [
{ givenName: "firstName" },
{ familyName: "lastName" },
{ "custom:data": "blabla" },
{ "custom:data2": "" },
{ "custom:data3": null },
];
const reduced = fields
.filter((f) => {
const key = Object.keys(f)[0];
return f[key] === "" || f[key] === null || f[key] === undefined
? false
: true;
})
.reduce((acc, curr) => {
const key = Object.keys(curr)[0];
acc[key] = curr[key];
return acc;
}, {});
console.log(reduced);
I have valid JSON with this structure
const myJSONExample = {
"SubItems": [
{
"SubItems": [
{
"ItemNo": "000001"
}
],
"ItemNo": null,
"Number": null,
"price": 114.46
},
{
"SubItems": [
{
"Group": "0.4.004"
}
],
"type": null
},
{
"SubItems": [
{
"ItemNo": "000005"
},
{
"Quantity": 2
}
],
"Material": "Steel"
},
{
"Description": null
}
]
}
and just simply trying to format all number types in it, using recursive iteration.
const iterate = (obj) => {
Object.keys(obj).forEach(key => {
if(typeof(item[key]) == "number"){
item[key] = new Intl.NumberFormat("de-DE").format(item[key]) //format number for german lang.
}
if (typeof obj[key] === 'object') {
iterate(obj[key])
}
})
}
iterate(myJSONExample);
I used this functions on other JSONs, and been trying to understand for some time, why this throws TypeError: Cannot convert undefined or null to object
null is an "object" hence your issue. So add a truthy check
const iterate = (obj) => {
Object.keys(obj).forEach(key => {
const value = obj[key]
const valueType = typeof value
if (valueType === "number") {
obj[key] = new Intl.NumberFormat("de-DE").format(value)
} else if (valueType === 'object' && value) {
iterate(value)
}
})
}
How can I parse the true and false strings in an array to become boolean in Javascript?
For instance,
from:
{"id":1,"dashboardId":1,"w":2,"h":2,"x":0,"y":0,"i":"n0","minW":1,"minH":1,"maxH":1000,"moved":"false","static":"false","widget":"Photo"}
to:
{"id":1,"dashboardId":1,"w":2,"h":2,"x":0,"y":0,"i":"n0","minW":1,"minH":1,"maxH":1000,"moved":false,"static":false,"widget":"Photo"}
The values from moved and static have to be a boolean but they appear as a string. Is there a way to only change those values?
This is the function where I fetch the arrays:
loadData = () => {
let dashboardId = 1;
return axios
.get('api/dashboards/' + dashboardId)
.then(result => {
//#TODO Parse true and false strings to become booleans
console.log(result);
this.setState({
items: result.data,
selectedOption: '',
newCounter: originalLayouts.length
});
})
.catch(error => {
console.log(JSON.stringify(this.state.items));
console.error('error: ', error);
})
};
parse the true and false strings in an array to become boolean
Strings in an array, you say? Iterate using Array.map()
const items = ["true", "false", "something else"]
const booleans = items.map(boolFromStringOtherwiseNull)
console.log({items, booleans}) // show result
function boolFromStringOtherwiseNull(s) {
if (s == 'true') return true
if (s == 'false') return false
return null
}
Objects? Iterate using Object.values()
const data = {"id":1,"dashboardId":1,"w":2,"h":2,"x":0,"y":0,"i":"n0","minW":1,"minH":1,"maxH":1000,"moved":"false","static":"false","widget":"Photo"};
const booleans = Object.values(data).map(boolFromStringOtherwiseNull); // convert
console.log({data, booleans}); // show result
function boolFromStringOtherwiseNull(s) {
if (s == 'true') return true
if (s == 'false') return false
return null
}
Convert only boolean strings, and maintain the original Object's structure?
const data = {"id":1,"dashboardId":1,"w":2,"h":2,"x":0,"y":0,"i":"n0","minW":1,"minH":1,"maxH":1000,"moved":"false","static":"false","widget":"Photo"}
const result = Object.entries(data)
.map(boolFromStringOtherwiseNoOp) // convert 'boolean strings' to boolean
.reduce(gatherObjectFromEntries, {}) // collect all entries into 1 object
console.log({data, result}); // result is an object where non-boolean-strings are untouched.
function boolFromStringOtherwiseNoOp([key, value]) {
if (value == 'true') return [key, true]
if (value == 'false') return [key, false]
return [key, value]
}
function gatherObjectFromEntries(accumulation, [key, value]) {
accumulation[key] = value
return accumulation
}
Hope this helps. Cheers,
You can iterate the object, and check its value strictly for "false" or "true" and parse them manually to boolean.
E.g.
function mapObjectValues (obj = {}) {
for (var key in obj) {
var val = obj[ key ];
if (val === "false") {
obj[ key ] = false;
}
else if (val === "true") {
obj[ key ] = true;
}
}
}
var tmp = {
"id": 1,
"dashboardId": 1,
"w": 2,
"h": 2,
"x": 0,
"y": 0,
"i": "n0",
"minW": 1,
"minH": 1,
"maxH": 1000,
"moved": "false",
"static": "false",
"widget": "Photo"
};
mapObjectValues(tmp);
console.log(tmp);
You can loop over the object keys and then compare those boolean strings and assign the actual Boolean value to that property:
var data = {"id":1,"dashboardId":1,"w":2,"h":2,"x":0,"y":0,"i":"n0","minW":1,"minH":1,"maxH":1000,"moved":"false","static":"false","widget":"Photo"};
Object.keys(data).forEach((key) => {
if(data[key] === 'false'){
data[key] = false;
}
if(data[key] === 'true'){
data[key] = true;
}
});
console.log(data);
You can do like this:
var data = { "id": 1, "dashboardId": 1, "w": 2, "h": 2, "x": 0, "y": 0, "i": "n0", "minW": 1, "minH": 1, "maxH": 1000, "moved": "false", "static": "false", "widget": "Photo" };
Object.keys(data).forEach((key) => {
if (data[key] === 'false' || data[key] === 'true') {
data[key] = JSON.parse(data[key]);
}
});
console.log(data);
`
for(key in a){
a[key] == "true" ? a[key] = true : a[key] == "false" ? a[key] = false : '';
}
You can simply loop over the object and use the ternary operator, to make it concise,
where a is your original object