convert javascript enum key string to value - javascript

In JavaScript code, I have the following enum defined:
MyMessageIds = {
UndefinedId : 0,
FilenameId : 1,
BuildFileId : 2,
MovementArgsId : 3,
MoveId : 4,
ExecuteCommandId : 5
}
In a JavaScript function, I would like to be able to supply the string representation of an enum key (i.e. "MoveId") and return its integer value of 4. So how could I do this?

Just use bracket notation:
var MyMessageIds = {
UndefinedId : 0,
FilenameId : 1,
BuildFileId : 2,
MovementArgsId : 3,
MoveId : 4,
ExecuteCommandId : 5
};
function getValue(key) {
return MyMessageIds[key];
}

You could create some utility methods which take an object (enum) that figures out how to get the keys/values.
var MyMessageIds = {
UndefinedId : 0,
FilenameId : 1,
BuildFileId : 2,
MovementArgsId : 3,
MoveId : 4,
ExecuteCommandId : 5
}
function getEnumKeys(enumType) {
return Object.keys(MyMessageIds);
}
function getEnumValues(enumType) {
return getEnumKeys(enumType).map(function(key) {
return enumType[key];
});
}
function getEnumValue(enumType, key) {
return enumType[getEnumKeys(enumType).filter(function(k) {
return key === k;
}).pop() || ''];
}
document.body.innerHTML = '<pre>' + JSON.stringify({
'Enum Keys' : getEnumKeys(MyMessageIds),
'Enum Vals' : getEnumValues(MyMessageIds),
'Example' : {
'MoveId' : getEnumValue(MyMessageIds, 'MoveId')
}
}, null, 4) + '</pre>';
You could also create your own class object to represent an enum which has reusable methods.
function Enum() {
this.self = arguments[0];
}
Enum.prototype = {
keys : function() {
return Object.keys(this.self);
},
values : function() {
var me = this;
return this.keys(this.self).map(function(key) {
return me.self[key];
});
},
getValueByName : function(key) {
return this.self[this.keys(this.self).filter(function(k) {
return key === k;
}).pop() || ''];
},
getNameByValue : function(value) {
var me = this;
return this.keys(this.self).filter(function(k) {
return me.self[k] === value;
}).pop() || null;
}
};
var MyMessageIds = new Enum({
UndefinedId : 0,
FilenameId : 1,
BuildFileId : 2,
MovementArgsId : 3,
MoveId : 4,
ExecuteCommandId : 5
});
document.body.innerHTML = '<pre>' + JSON.stringify({
'Enum Keys' : MyMessageIds.keys(),
'Enum Vals' : MyMessageIds.values(),
'Example' : {
'MoveId' : MyMessageIds.getValueByName('MoveId'),
'Val(3)' : MyMessageIds.getNameByValue(3)
}
}, null, 4) + '</pre>';

Related

Created a nested Json structure from an Javascript array

I'm looking to create a valid nested Json file, from an array, with unique keys value. Currently, I'm only able to to display the json without any nested structure.
I would like to display to the console the following structure :
{
"Key" : "data1",
"header" : {
"title" : "data2",
"tag1" : "data3",
"tag2" : "data4"
},
"body" : {
"text" : "data5"
},
"updates" : {
"title" : "data6",
"text" : "data7"
},
"footer" : {
"title" : "data8",
"row1" :{
"col1" : {
"title" : "data9",
"text" : "data10"
},
"col2" : {
"title" : "data11",
"text" : "data12"
},
"col3" : {
"title" : "data13",
"text" : "data14"
}
},
"row2" :{
"col1" : {
"title" : "data15",
"text" : "data16"
},
"col2" : {
"title" : "data17",
"text" : "data18"
},
"col3" : {
"title" : "data19",
"text" : "data20"
}
},
"row3" :{
"col1" : {
"title" : "data22",
"text" : "data23"
},
"col2" : {
"title" : "data24",
"titlebis" : "data25",
"text" : "data26"
},
"col3" : {
"title" : "data27",
"text" : "data28"
}
},
"row4" :{
"col1" : {
"title" : "data29"
},
"website" : "data30",
"website-link" : "data31",
"email" : "data38",
"privacy" : "data32",
"privacy-link" : "data33",
"adr" : "data34",
"adr2" : "data35"
}
},
"other" : {
"short" : {
"des" : "data36"
},
"promovideo" : "data37"
}
}
here is what I already done:
var data = [["Key", "data1"],
["header.title", "data2"],
["header.tag1", "data3"],
["header.tag2", "data4"],
["body.text", "data5"],
["updates.title", "data6"],
["updates.text", "data7"],
["footer.title", "data8"],
["footer.row1.col1.title", "data9"],
["footer.row1.col1.text", "data10"],
["footer.row1.col2.title", "data11"],
["footer.row1.col2.text", "data12"],
["footer.row1.col3.title", "data13"],
["footer.row1.col3.text", "data14"],
["footer.row2.col1.title", "data15"],
["footer.row2.col1.text", "data16"],
["footer.row2.col2.title", "data17"],
["footer.row2.col2.text2", "data18"],
["footer.row2.col3.title", "data19"],
["footer.row2.col3.text", "data20"],
["footer.row3.col1.title", "data22"],
["footer.row3.col1.text", "data23"],
["footer.row3.col2.title", "data24"],
["footer.row3.col2.title", "data25"],
["footer.row3.col2.text", "data26"],
["footer.row3.col3.title", "data27"],
["footer.row3.col3.text", "data28"],
["footer.row4.col1.title", "data29"],
["footer.row4.website", "data30"],
["footer.row4.website-link", "data31"],
["footer.row4.email", "data31"],
["footer.row4.privacy", "data32"],
["footer.row4.privacy-link", "data33"],
["footer.row4.adr", "data34"],
["footer.row4.adr2", "data35"],
["other.short.des", "data36"],
["other.promovideo", "data37"],
];
// console.log(data);
data.sort(alphabetical); // Sort alphabetically our 2D array
CreateAndDisplayJson(data);
// Create a JSON file from Keys Trad Data
function CreateAndDisplayJson(GetKeysTraductionArrayData) {
var lenght = GetKeysTraductionArrayData.length;
var output = "{\n";
for (var i = 0; i < GetKeysTraductionArrayData.length; i++) {
var key = GetKeysTraductionArrayData[i][0];
var trad = GetKeysTraductionArrayData[i][1];
var nameSplit = key.split("."); // Check how many times we need to indent json from Key
if(nameSplit.length>1) { // The Key needs to be indented
var closeBraket = "";
var spacing = ""; // Json indentation
var saveSpacingTab = []; // Closing indentation
for (j=0; j <nameSplit.length; j++){ // We add the key + indentation
output += spacing+"\""+nameSplit[j]+"\" : { \n";
if (j==0 && i != GetKeysTraductionArrayData.length-1) {
closeBraket = spacing+"}, \n";
} else {
closeBraket = spacing+"} \n";
}
spacing +=" ";
saveSpacingTab[j] = closeBraket;
closingText = "";
if (j==nameSplit.length-1) { // last indentation of the Key
saveSpacingTab.reverse();
for ( k=0; k < saveSpacingTab.length ; k++) { // We create the Bracket indentation
closingText += saveSpacingTab[k];
}
output += spacing+"\""+nameSplit[j]+"\" : " + "\""+trad +"\"\n" + closingText; // last Row
}
}
} else {
output += "\""+key+"\" : " + "\""+trad +"\", \n";
}
}
// output += "}" + outputCommented;
output += "}";
console.log(output);
return output;
}
// Sort alphabetically our 2D array
function alphabetical(a, b) {
var A = a[0];
var B = b[0].toLowerCase();
A = A.toLowerCase();
B = B.toLowerCase();
if (A < B) return -1;
if (A > B) return 1;
return 0;
}
You can use forEach loop and inside split each key and then use reduce to build nested structure for each key.
var data = [["Key","data1"],["header.title","data2"],["header.tag1","data3"],["header.tag2","data4"],["body.text","data5"],["updates.title","data6"],["updates.text","data7"],["footer.title","data8"],["footer.row1.col1.title","data9"],["footer.row1.col1.text","data10"],["footer.row1.col2.title","data11"],["footer.row1.col2.text","data12"],["footer.row1.col3.title","data13"],["footer.row1.col3.text","data14"],["footer.row2.col1.title","data15"],["footer.row2.col1.text","data16"],["footer.row2.col2.title","data17"],["footer.row2.col2.text2","data18"],["footer.row2.col3.title","data19"],["footer.row2.col3.text","data20"],["footer.row3.col1.title","data22"],["footer.row3.col1.text","data23"],["footer.row3.col2.title","data24"],["footer.row3.col2.title","data25"],["footer.row3.col2.text","data26"],["footer.row3.col3.title","data27"],["footer.row3.col3.text","data28"],["footer.row4.col1.title","data29"],["footer.row4.website","data30"],["footer.row4.website-link","data31"],["footer.row4.email","data31"],["footer.row4.privacy","data32"],["footer.row4.privacy-link","data33"],["footer.row4.adr","data34"],["footer.row4.adr2","data35"],["other.short.des","data36"],["other.promovideo","data37"]]
let result = {}
data.forEach(([key, value]) => {
key.split('.').reduce((r, k, i, arr) => {
return r[k] || (r[k] = arr[i + 1] ? {} : value)
}, result)
})
console.log(result)
A non-ternary solution with reduce:
const data = [["Key","data1"],["header.title","data2"],["header.tag1","data3"],["header.tag2","data4"],["body.text","data5"],["updates.title","data6"],["updates.text","data7"],["footer.title","data8"],["footer.row1.col1.title","data9"],["footer.row1.col1.text","data10"],["footer.row1.col2.title","data11"],["footer.row1.col2.text","data12"],["footer.row1.col3.title","data13"],["footer.row1.col3.text","data14"],["footer.row2.col1.title","data15"],["footer.row2.col1.text","data16"],["footer.row2.col2.title","data17"],["footer.row2.col2.text2","data18"],["footer.row2.col3.title","data19"],["footer.row2.col3.text","data20"],["footer.row3.col1.title","data22"],["footer.row3.col1.text","data23"],["footer.row3.col2.title","data24"],["footer.row3.col2.title","data25"],["footer.row3.col2.text","data26"],["footer.row3.col3.title","data27"],["footer.row3.col3.text","data28"],["footer.row4.col1.title","data29"],["footer.row4.website","data30"],["footer.row4.website-link","data31"],["footer.row4.email","data31"],["footer.row4.privacy","data32"],["footer.row4.privacy-link","data33"],["footer.row4.adr","data34"],["footer.row4.adr2","data35"],["other.short.des","data36"],["other.promovideo","data37"]]
const result = data.reduce((all, [keys, val]) => {
keys.split('.').reduce((obj, key, i, arr) => {
if (i === arr.length - 1) {
obj[key] = val;
} else {
if (!obj.hasOwnProperty(key)) {
obj[key] = {};
};
}
return obj[key];
}, all);
return all;
}, {});
console.log(result);

javascript return property value from nested array of objects based on condition

i have an array of objects, in which each object could have an array of objects inside.
var mylist = [
{
"email" : null,
"school" : "schoolA",
"courses": [
{
"name" : 'ABC',
"type" : "chemistry"
},
{
"name" : 'XYZ',
"type": "math"
}
]
},
{
"email" : null,
"school": "schoolB"
}
];
i want to return course name if one of the course type is chemistry.
The course types are unique and even if they are some duplicates, we return the first one.
var result = mylist.some(function (el) {
el.courses && el.courses.some(function(u) {
if (u.type === 'chemistry') {
return u.name;
};
})
});
console.log('outcome:', result);
my code is not working at this stage.
The some callback should return a truthy or falsy value, which tells some whether to keep going (true = stop), and some returns a boolean, not a callback return value.
Probably simplest in this case just to assign directly to result:
var result;
mylist.some(function(el) {
return (el.courses || []).some(function(course) {
if (course.type === "chemistry") {
result = course.name;
return true;
}
return false;
});
});
Live Example:
var mylist = [
{
"email" : null,
"school" : "schoolA",
"courses": [
{
"name" : 'ABC',
"type" : "chemistry"
},
{
"name" : 'XYZ',
"type": "math"
}
]
},
{
"email" : null,
"school": "schoolB"
}
];
var result;
mylist.some(function(el) {
return (el.courses || []).some(function(course) {
if (course.type === "chemistry") {
result = course.name;
return true;
}
return false;
});
});
console.log(result);
I stuck to ES5 syntax since you didn't use any ES2015+ in your question, but in ES2015+, simplest probably to use nested for-of loops:
let result;
outer: for (const el of mylist) {
for (const course of el.courses || []) {
if (course.type === "chemistry") {
result = course.name;
break outer;
}
}
}
Live Example:
const mylist = [
{
"email" : null,
"school" : "schoolA",
"courses": [
{
"name" : 'ABC',
"type" : "chemistry"
},
{
"name" : 'XYZ',
"type": "math"
}
]
},
{
"email" : null,
"school": "schoolB"
}
];
let result;
outer: for (const el of mylist) {
for (const course of el.courses || []) {
if (course.type === "chemistry") {
result = course.name;
break outer;
}
}
}
console.log(result);
You could use reduce() method to iterate through each object in array and then find() method to find if some course matches type.
var mylist = [{"email":null,"school":"schoolA","courses":[{"name":"ABC","type":"chemistry"},{"name":"XYZ","type":"math"}]},{"email":null,"school":"schoolB"}]
const course = mylist.reduce((r, {courses}) => {
if (courses && !r) {
const course = courses.find(({type}) => type == 'chemistry');
if (course) r = course.name;
}
return r;
}, null)
console.log(course)

How to Combine or Merge Object Array with Object Array Jquery

i have an object like this in my console:
ObjectName1 : Array(3)
0 : { id : 1, name : 'foo' },
1 : { id : 2, name : 'foo-2' },
2 : { id : 3, name : 'foo-3' },
ObjectName2 : Array(3)
0 : { id : 1, foo : 'bar' },
1 : { id : 2, foo-2 : 'bar-2' },
2 : { id : 3, foo-3 : 'bar-3' },
and as usually if we want to get the name, just write : ObjectName1[key].name right ?
now if i want to get the key from ObjectName2 (foo, foo-2, foo-3) how to get the key from ObjectName2 using the value from ObjectName1 ?
i have written like this :
// just say there is an each above this comment
var name = ObjectName1[key].name;
var bar = ObjectName2[key]+"."+name;
// end each
but it just showed
[Object object].foo
[Object object].foo-2
[Object object].foo-3
the output should be like this :
bar
bar-2
bar-3
it is possible doing like i want to do ? help me please if it is possible
any help will be very appreciated.
*note : i'm not sure what is the case name in my problem, so forgive me if the title went wrong
thanks
Try this one. Loop through each object in ObjectName1 object and get the name in appropriate index, this name will be the key for the ObjectName2 object. Then use that key to print the appropriate value from ObjectName2
var ObjectName1 = [{'id' : 1, 'name' : 'foo'}, {'id' : 2, 'name' : 'foo-2'}, {'id' : 3, 'name' : 'foo-3'}];
var ObjectName2 = [{'id' : 1, 'foo' : 'bar'}, {'id' : 2, 'foo-2' : 'bar-2'}, {'id' : 3, 'foo-3' : 'bar-3'}];
for(var i = 0; i < ObjectName2.length; i++){
console.log(ObjectName2[i][ObjectName1[i]['name']]);
}
Something like this?
var name = ObjectName1[key].name;
ObjectName2.forEach(function(a) {
if (a.keys().includes(name)) {
var bar = a[name];
// then do what you want with bar
}
}
As commented, your key is an object. Hence, it is showing [Object object].foo-3.
You will have to use 2 loops and check if the key is inside current object. If yes, print it, else continue.
var ObjectName1 =[
{ id : 1, name : 'foo' },
{ id : 2, name : 'foo-2' },
{ id : 3, name : 'foo-3' },
]
var ObjectName2 = [
{ id : 1, foo : 'bar' },
{ id : 2, 'foo-2' : 'bar-2' },
{ id : 3, 'foo-3' : 'bar-3' },
];
ObjectName1.forEach(function(obj){
ObjectName2.forEach(function(obj2){
var key = obj.name;
if(key in obj2){
console.log(obj2[key])
}
})
})
now if i want to get the key from ObjectName2 (foo, foo-2, foo-3) how to get the key from ObjectName2 using the value from ObjectName1 ?
If you know those are parallel arrays (where [0] in one array is intentionally a match for [0] in the other array), you can simply loop through:
ObjectName1.forEach(function(entry1, index) {
var value = ObjectName2[index][entry1.name];
console.log(entry1.name + " = " + value);
});
Example:
var ObjectName1 = [
{ id : 1, name : 'foo' },
{ id : 2, name : 'foo-2' },
{ id : 3, name : 'foo-3' }
];
var ObjectName2 = [
{ id : 1, "foo" : 'bar' },
{ id : 2, "foo-2" : 'bar-2' },
{ id : 3, "foo-3" : 'bar-3' }
];
ObjectName1.forEach(function(entry1, index) {
var value = ObjectName2[index][entry1.name];
console.log(entry1.name + " = " + value);
});
That assumes you know they're parallel arrays.
If not, you have to search for it. Array.prototype.findIndex will return the index of the first element where a callback returns true:
ObjectName1.forEach(function(entry1) {
console.log("entry1.name = " + entry1.name);
var index = ObjectName2.findIndex(function(entry2) {
// See if entry2 contains a key with that value
return entry1.name in entry2;
});
console.log(index == -1 ? "Not found" : ("Found at index #" + index + ", value = " + ObjectName2[index][entry1.name]));
});
Example:
var ObjectName1 = [
{ id : 1, name : 'foo' },
{ id : 2, name : 'foo-2' },
{ id : 3, name : 'foo-3' }
];
var ObjectName2 = [
{ id : 1, "foo" : 'bar' },
{ id : 2, "foo-2" : 'bar-2' },
{ id : 3, "foo-3" : 'bar-3' }
];
ObjectName1.forEach(function(entry1) {
console.log("entry1.name = " + entry1.name);
var index = ObjectName2.findIndex(function(entry2) {
// See if entry2 contains a key with that value
return entry1.name in entry2;
});
console.log(index == -1 ? "Not found" : ("Found at index #" + index + ", value = " + ObjectName2[index][entry1.name]));
});
If you don't really need the key (e.g., index) of the matching object in ObjectName2, just the object, use find instead:
ObjectName1.forEach(function(entry1) {
console.log("entry1.name = " + entry1.name);
var entry = ObjectName2.find(function(entry2) {
// See if entry2 contains a key with that value
return entry1.name in entry2;
});
console.log(!entry ? "Not found" : ("Found, value is " + entry[entry1.name]));
});
Example:
var ObjectName1 = [
{ id : 1, name : 'foo' },
{ id : 2, name : 'foo-2' },
{ id : 3, name : 'foo-3' }
];
var ObjectName2 = [
{ id : 1, "foo" : 'bar' },
{ id : 2, "foo-2" : 'bar-2' },
{ id : 3, "foo-3" : 'bar-3' }
];
ObjectName1.forEach(function(entry1) {
console.log("entry1.name = " + entry1.name);
var entry = ObjectName2.find(function(entry2) {
// See if entry2 contains a key with that value
return entry1.name in entry2;
});
console.log(!entry ? "Not found" : ("Found, value is " + entry[entry1.name]));
});

I don't know how to implementate the function reduce

I do not know how to implement the reduce function.
I have output from my map a document as ...
for example two documents
key "_id":"AD"
"values"
{
"numtweets" : 1,
"hastags" : {
"OPINIÓ" : 1,
"debat" : 1,
"inexistent" : 1,
"tampoc" : 1,
"promet" : 1,
"gaire" : 1,
"diàleg" : 1
}
}
and other
{
"numtweets" : 1,
"hastags" : {
"other" : 1,
"debat" : 1,
"inexistent" : 1,
"another" : 1,
}
}
I need a function that reduces all sum so that
"numtweets" : 2,
"dicwords" : {
"OPINIÓ" : 1,
"debat" : 2,
"inexistent" : 2,
"tampoc" : 1,
"promet" : 1,
"gaire" : 1,
"diàleg" : 1,
"other" : 1,
"another" : 1
},
"lisuser" : {
"user2" : 1
}
if my json values was only nuwtweets the reduce is
function(key, values) {
return Array.sum(values);
};
if mi json values only was hastags (without numtweets and lisuser) the reduce function was
var r = function(key, values) {
result = {}
values.forEach(function(val) {
for (hashtag in val) {
if (hashtag in result) {
result[hashtag] = result[hashtag] + val[hashtag]
} else {
result[hashtag] = val[hashtag]
}
}
});
return(result)
};
But I don't know how mix the 2 reduce function.
My level of mongodb and JavaScript is very low.
Thanks
Try this:
let data = values.reduce((finalObj, ele) => {
finalObj.numtweets += ele.numtweets
for (key in ele.hastags) {
if(ele.hastags.hasOwnProperty(key)) {
if(finalObj.hastags[key])
finalObj.hastags[key] += ele.hastags[key]
else
finalObj.hastags[key] = ele.hastags[key]
}
}
return finalObj
})
console.log(data)
Where values is array for objects which you want reduce to one object

Remove extra properties from object

What would be the best way to remove any additional properties from an object that is not defined in defaults object?
var
defaults = {
color : 'blue',
size: 9,
price : 40.00,
instock : true
},
newItem = {
color: 'red',
size : 4,
price : 20.00
extra : invalid // discard this
extra1 : invalid // discard this
},
item = $.extend( defaults, newObject ) ;
Desired output....
{
color : 'red',
size: 4,
price : 20.00,
instock : true
}
You could reduce Object.keys(defaults) to an object containing either the override value or the default value:
var defaults = {
color : 'blue',
size: 9,
price : 40.00,
instock : true
},
newItem = {
color: 'red',
size : 4,
price : 20.00,
extra : 'invalid',
extra1 : 'invalid'
};
function getOverrides(defaults, obj) {
return Object.keys(defaults).reduce(function(result, cur) {
result[cur] = cur in obj ? obj[cur] : defaults[cur];
return result;
}, {});
}
console.log(getOverrides(defaults, newItem));
According to this performance comparison:
https://jsperf.com/dictionary-contains-key
The most efficient way to do this is:
for(attr in newItem) {
if(defaults[attr] === undefined)
delete newItem[attr];
}
Before you call $.extend, put the following.
for(variable in newItem) {
if(!(variable in defaults)) {
delete newItem[variable];
}
}
This will loop over every key in newItem and check that it is also a key in defaults. Note that this will modify newItem, so if that is not desired, you'll need to do some tweaking.
Only merge properties which existing in defaults object: (simple and supports old browsers)
var defaults = {
color : 'blue',
size: 9,
price : 40.00,
instock : true
};
var newItem = {
color: 'red',
size : 4,
price : 20.00,
extra : 'invalid', // discard this
extra1 : 'invalid' // discard this
};
var result = {};
for (var i in defaults) {
result[i] = newItem.hasOwnProperty(i) ? newItem[i] : defaults[i];
}
console.log(result);
Some code that I have been playing with that may be of interest, and an example of how to use it with your question.
'use strict';
var slice = Function.call.bind(Array.prototype.slice);
var reflectAssign = function assign(target) {
return slice(arguments, 1).every(function(source) {
if (source == null) {
return true;
}
var object = Object(source);
return Reflect.ownKeys(object).every(function(key) {
return Reflect.set(target, key, object[key]);
});
});
};
var reflectAssignHas = function(target) {
var targetKeys = Reflect.ownKeys(target);
return slice(arguments, 1).every(function(source) {
if (source == null) {
return true;
}
var object = Object(source);
return targetKeys.every(function(key) {
return Reflect.has(object, key) ? Reflect.set(target, key, object[key]) : true
});
});
};
var defaults = {
color: 'blue',
size: 9,
price: 40.00,
instock: true
};
var newItem = {
color: 'red',
size: 4,
price: 20.00,
extra: 'invalid', // discard this
extra1: 'invalid' // discard this
};
var item = {};
console.log(reflectAssign(item, defaults));
console.log(reflectAssignHas(item, newItem));
console.log(item);
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-sham.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.3/es6-shim.js"></script>

Categories