MongoDB/JS Create Object Key from String - javascript

I have a string such as :
key = "person.name.first"
Is it possible to convert that to...
{
person: {
name: {
first: '????'
}
}
}

You could write a small recursive utility function to achieve this in java script
var key = "person.name.first".split("\.");
var obj = {};
function create(o,index){
if(index > key.length-1) return;
o[key[index]] = {};
index++;
create(o[key[index-1]],index);
}
// Call the recursive function:
create(obj,0);
Then you could set the value as: person.name.first = "value";
If you would want to set the values, or dynamically set the type of each field such as an array or object, you could have an mapping array, which holds the type for each field and could be read during the creation.

Related

How to get the opposite property?

I have the following object with (always) 2 properties. It wil always have 2 properties. 3 properties won't be possible:
var people = {
'John': { ... },
'Peter': { ... }
}
And I have the variable var name = 'John'.
Is there a simple way to get the value of property 'Peter' when the value of name is 'John'?
Without hard-coding it with the names John en Peter. So the functionality must get the opposite property of the value in variable name
let name = 'John'; // or whatever
let names = Object.keys(people);
let otherName = names.find(n => n !== name);
people[otherName] // this gives you the value of the other name's property
Object.keys will give you an array of the property names.
filter lets you filter that array.
So:
const name = "John";
const people = {
'John': 1,
'Peter': 1
};
const [result] = Object.keys(people).filter(person => person !== name);
console.log({
result
});
I wrote a simple function, that does this. It takes a key, and an object. It returns the value of the element in the given object by the inverse key of the given key. This will only work if the object only has two keys.
var people = {
'John': { 'b':[3,4] },
'Peter': { 'a':[1,2] }
}
getInverseObjectElem = (key,object) => { // Define function 'getInverseObjectElem'
listOfObjectKeys = Object.keys(object) // Create an array of the object keys
inverseKey = listOfObjectKeys.filter(k => k != key)[0] // filter the list of keys, and get the first key that doesnt match the given key.
return object[inverseKey] // Return the value in the object, by the inverseKey
}
console.log(getInverseObjectElem('John',people))
You could try this:
for (let key in people){
if (key != name) return people[key];
}

Not able to send value to frontend [duplicate]

I must be missing something here, but the following code (Fiddle) returns an empty string:
var test = new Array();
test['a'] = 'test';
test['b'] = 'test b';
var json = JSON.stringify(test);
alert(json);
What is the correct way of JSON'ing this array?
JavaScript arrays are designed to hold data with numeric indexes. You can add named properties to them because an array is a type of object (and this can be useful when you want to store metadata about an array which holds normal, ordered, numerically indexed data), but that isn't what they are designed for.
The JSON array data type cannot have named keys on an array.
When you pass a JavaScript array to JSON.stringify the named properties will be ignored.
If you want named properties, use an Object, not an Array.
const test = {}; // Object
test.a = 'test';
test.b = []; // Array
test.b.push('item');
test.b.push('item2');
test.b.push('item3');
test.b.item4 = "A value"; // Ignored by JSON.stringify
const json = JSON.stringify(test);
console.log(json);
Nice explanation and example above. I found this (JSON.stringify() array bizarreness with Prototype.js) to complete the answer. Some sites implements its own toJSON with JSONFilters, so delete it.
if(window.Prototype) {
delete Object.prototype.toJSON;
delete Array.prototype.toJSON;
delete Hash.prototype.toJSON;
delete String.prototype.toJSON;
}
it works fine and the output of the test:
console.log(json);
Result:
"{"a":"test","b":["item","item2","item3"]}"
I posted a fix for this here
You can use this function to modify JSON.stringify to encode arrays, just post it near the beginning of your script (check the link above for more detail):
// Upgrade for JSON.stringify, updated to allow arrays
(function(){
// Convert array to object
var convArrToObj = function(array){
var thisEleObj = new Object();
if(typeof array == "object"){
for(var i in array){
var thisEle = convArrToObj(array[i]);
thisEleObj[i] = thisEle;
}
}else {
thisEleObj = array;
}
return thisEleObj;
};
var oldJSONStringify = JSON.stringify;
JSON.stringify = function(input){
if(oldJSONStringify(input) == '[]')
return oldJSONStringify(convArrToObj(input));
else
return oldJSONStringify(input);
};
})();
Another approach is the JSON.stringify() replacer function param. You can pass a 2nd arg to JSON.stringify() that has special handling for empty arrays as shown below.
const arr = new Array();
arr.answer = 42;
// {"hello":"world","arr":{"answer":42}}
JSON.stringify({ hello: 'world', arr }, function replacer(key, value) {
if (Array.isArray(value) && value.length === 0) {
return { ...value }; // Converts empty array with string properties into a POJO
}
return value;
});
Alternatively you can use like this
var test = new Array();
test[0]={};
test[0]['a'] = 'test';
test[1]={};
test[1]['b'] = 'test b';
var json = JSON.stringify(test);
alert(json);
Like this you JSON-ing a array.
Json has to have key-value pairs. Tho you can still have an array as the value part. Thus add a "key" of your chousing:
var json = JSON.stringify({whatver: test});

Adding a key/value pair at the same time as creating a sub-object

I am new to working with objects. I want to:
Add a key
Add a sub-object to that key
Push the key/value pair to this sub-object.
For example, the data structure I am looking to achieve would be:
invalidFields = {
"_0" : {
"firstName" : "foo",
"lastName" : "la",
}
}
The addition of the most nested key/value pair is done by iterating and comparing, so in essence it needs to be added to "_0", not overwriting it.
So far I have:
let invalidFields = {}; // this is initialised outside of the for loop
...
const field = "foo";
const passengerIdentifier = "_" + passengerIndex; // "_0"
const fieldKey = "firstName";
invalidFields[passengerIdentifier] = field;
This adds the key/value pair of "firstName": "foo" but when the loop continues it therefore overwrites it so the data I get is only field applied :
invalidFields = {
"_0" : "foo",
}
This is obviously not correct as I need the key/value pairs to add to the "_0" sub-object. What am I doing wrong?
Edit: Here is an example of what I have now, but this does not seem to work, the field part isn't added:
const passengerIdentifier = '_'+passengerIndex;
if (!invalidFields[passengerIdentifier]) {
Object.assign(invalidFields, { [passengerIdentifier] : '' });
Object.assign(invalidFields[passengerIdentifier], { [fieldKey]: field });
}
To add key/value pair to each sub-object use the following approach:
...
var field = "foo",
passengerIdentifier = "_" + passengerIndex, // "_0"
fieldKey = "firstName";
// assuring sub-object with certain `passengerIdentifier`
invalidFields[passengerIdentifier] = invalidFields[passengerIdentifier] || {};
invalidFields[passengerIdentifier][fieldKey] = field;
You could use Object.assign and add the new key/value to the existing object in the loop.
// outside of the loop
invalidFields[passengerIdentifier] = {};
// inside of the loop
Object.assign(invalidFields[passengerIdentifier], { [fieldKey]: field });
Just for completeness, it is possible, to assign a value directly to an object
// inside of the loop
invalidFields[passengerIdentifier][fieldKey] = field;
let invalidFields = {}; // this is initialised outside of the for loop
...
const field = "foo";
const passengerIdentifier = "_" + passengerIndex; // "_0"
const fieldKey = "firstName";
var subObject = {
'key1' : value1,
'key2' : value2,
// add all keys
}
invalidFields[passengerIdentifier] = subObject ;
Does this do what you're trying to achieve?
invalidFields[passengerIdentifier] = {
[fieldKey]: field
}

Is it necessary to create nested jSON objects before using it?

I think I've seen how to create a JSON object without first preparing it. This is how i prepare it:
obj = {
0:{
type:{}
},
1:{},
2:{}
};
Now I think I can insert a value like: obj.0.type = "type0"; But I'd like to create it while using it: obj['0']['type'] = "Type0";.
Is it possible, or do I need to prepare it? I'd like to create it "on the fly"!
EDIT
I'd like to create JS object "On the fly".
var obj = {};
obj.test = "test"; //One "layer" works fine.
obj.test.test = "test" //Two "layers" do not work... why?
obj = {
0:{
type:{}
},
1:{},
2:{}
};
Now i think i can insert value like: obj.0.type = "type0";
I guess you mean "assign" a value, not "insert". Anyway, no, you can't, at least not this way, because obj.0 is invalid syntax.
But I'd like to create it while using it: obj['0']['type'] = "Type0";
That's fine. But you need to understand you are overwriting the existing value of obj[0][type], which is an empty object ({}), with the string Type0. To put it another way, there is no requirement to provide an initialized value for a property such as type in order to assign to it. So the following would have worked equally well:
obj = {
0:{},
1:{},
2:{}
};
Now let's consider your second case:
var obj = {};
obj.test = "test"; //One "layer" works fine.
obj.test.test = "test" //Two "layers" do not work... why?
Think closely about what is happening. You are creating an empty obj. You can assign to any property on that object, without initializing that property. That is why the assignment to obj.test works. Then in your second assignment, you are attempting to set the test property of obj.test, which you just set to the string "test". Actually, this will work--because strings are objects that you can set properties on. But that's probably not what you want to do. You probably mean to say the previous, string value of obj.test is to be replaced by an object with its own property "test". To do that, you could either say
obj.test = { test: "test" };
Or
obj.test = {};
obj.test.test = "test";
You are creating a plain object in JavaScript and you need to define any internal attribute before using it.
So if you want to set to "Type0" an attribute type, inside an attribute 0 of an object obj, you cannot simply:
obj['0']['type'] = "Type0";
You get a "reference error". You need to initialize the object before using it:
var obj = {
0: {
type: ""
}
};
obj['0']['type'] = "Type0";
console.log(obj['0']['type']);
You could create your own function that takes key as string and value and creates and returns nested object. I used . as separator for object keys.
function create(key, value) {
var obj = {};
var ar = key.split('.');
ar.reduce(function(a, b, i) {
return (i != (ar.length - 1)) ? a[b] = {} : a[b] = value
}, obj)
return obj;
}
console.log(create('0.type', 'type0'))
console.log(create('lorem.ipsum.123', 'someValue'))
Is it necessary to create nested objects before using it?
Yes it is, at least the parent object must exist.
Example:
var object = {};
// need to assign object[0]['prop'] = 42;
create the first property with default
object[0] = object[0] || {};
then assign value
object[0]['prop'] = 42;
var object = {};
object[0] = object[0] || {};
object[0]['prop'] = 42;
console.log(object);
Create object with property names as array
function setValue(object, keys, value) {
var last = keys.pop();
keys.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var object = {};
setValue(object, [0, 'prop'], 42);
console.log(object);

How do I access a Javascript 2D array of objects?

I have a global array that I declare as
var fileMappings = [];
I do some work, and add a row to the array like so:
fileMappings.push({ buttonNumber: number, audioFile: file });
if I do a JSON.stringify(fileMappings) I get this:
[{“buttonNumber”:”btn11”,”audioFile”:{0A0990BC-8AC8-4C1C-B089-D7F0B30DF858}},
{“buttonNumber”:”btn12”,”audioFile”:{2FCC34A6-BD1A-4798-BB28-131F3B546BB6}},
{“buttonNumber”:”btn13”,”audioFile”:{53A206EC-7477-4E65-98CC-7154B347E331}}]
How can I access the GUID for "btn11", etc?
Since Javascript arrays don't have support for keys, I would suggest that you use an object. Otherwise, you have to iterate through the entire array every time to look for the desired key.
var fileMappings = {};
And instead of push(), define a new property :
fileMappings[number] = { buttonNumber: number, audioFile: file };
This way, you can access your object with fileMappings['btn11']
You can iterate over the array's members to find the button, then return its GUID:
function findGUID(arr, buttonNumber) {
for (var i=0, iLen=arr.length; i<iLen; i++) [
if (arr[i].buttonNumber == buttonNumber) {
return arr[i].audioFile;
}
}
// return undefined - buttonNumber not found
}
Or if you want to use ES5 features:
function getGUID(arr, buttonNumber) {
var guid;
arr.some(function(obj) {
return obj.buttonNumber == buttonNumber && (guid = obj.audioFile);
});
return guid;
}
but I think the first is simpler and easier to maintain.

Categories

Resources