I am working on a function where I pass an object (record) to a function. It then loops over the keys and checks to see if that key is in our second object (lookup). If there is a match, it replaces the value in our record with a manipulated version (turns it into a link). If there is no match, it keeps its original value.
This is what I am passing to the function:
{ Source: "1234", NTID: "joeBob", Department: "x123", Email: 'joebob#example.com' }
-Here is the function
function createLink2(record) {
// Link types
var output = {
'ntid': 'https://example.com/profile/',
'email': 'mailTo:'
};
// Vars
var i,
key,
keys = Object.keys(output);
// Loop over our object keys
Object.keys(record).forEach(function(k, ind) {
// Loop over each of the link types
for ( i = 0; i < keys.length; ++i ) {
key = keys[i];
// If our key matches that of our object, turn it into a link
if(k.toLowerCase() == key){
record = ''+record[k]+'';
}else{
// Return the original value of the property since its not a match. Not quite sure how to do this part.
}
}
});
return record;
}
My goal here is that it would replace the value of Email with joeBob#example.com and NTID with joeBob.
The issue I am having is with the return - Not quite sure how to edit the data and return the full object back.
change this line:
record = ''+record[k]+'';
to this:
record[k] = ''+record[k]+'';
Of course, you could do this more easily by referring to the properties of the object directly:
function createLink2(record) {
// Link types
var output = {
'NTID': 'https://example.com/profile/',
'Email': 'mailTo:'
};
// Loop over the output keys
Object.keys(output).forEach(function(k, ind) {
if(record.hasOwnProperty(k)) {
record[k] = '' + record[k] + '';
}
});
return record;
}
Note that you don't really need to return it since the contents of the object will be changed directly as mentioned by others in the comments.
Javascript objects are passed by reference. So if you modify the object in the function it will be enough. Example:
function test(obj) {
obj.a = 10
}
var x = {a: 2};
test(x);
console.log(x.a) //prints 10
So, all you have to do is modify the value of "Email" with whatever you want.
You can iterate over an array and return an object using .reduce()
function createLink2(record) {
// Link types
var output = {
'ntid': 'https://example.com/profile/',
'email': 'mailTo:'
};
// Vars
var keys = Object.keys(output);
// Loop over our object keys
record = keys.reduce(function(obj, currKey) {
if (obj[currKey] != undefined) {
obj[currKey] = '' + obj[currKey] + ''
}
return obj;
}, record);
return record;
}
console.log(createLink2({ntid: "12345", email: "joebob#gmail.com"}));
Related
I am trying to get a json object returned from this function here's the code this runs and logs for example "firstname john" which is what i am expecting.
var req = { 'body' : {
'firstname':'john',
'middlename':'matrix',
'lastname':'smith',
'test' :'jesus'}
};
var targets = ['firstname' , 'middlename', 'lastname'];
for (var i = 0; i < Object.keys(req.body).length; i++) {
if(targets.includes(Object.keys(req.body)[i])){
console.log(Object.keys(req.body)[i], req.body[Object.keys(req.body)[i]]);
}
}
if i make the console.log() log an object instead of a string for example:
console.log({Object.keys(req.body)[i] : req.body[Object.keys(req.body)[i]]});
it throws a syntax error, is there a better way to do this/how can i get this to work?
If you were to stick with the Object.keys approach, you should call it once and capture the value so that your code is more efficient and easier to read:
var keys = Object.keys(req.body);
for (var i = 0; i < keys.length; i++) {
if(targets.includes(keys[i])){
console.log(keys[i], req.body[keys[i]]);
}
}
You could simplify quite a bit by working with the object instead of an array
var req = { 'body' : {
'firstname':'john',
'middlename':'matrix',
'lastname':'smith',
'test' :'jesus'}
};
var targets = ['firstname' , 'middlename', 'lastname'];
for (var prop in req.body) {
if (targets.includes(prop)) {
console.log(`${prop}: ${req.body[prop]}`)
// as an object
console.log({ [prop]: req.body[prop] })
}
}
You can use for function for objects, the first parameter referring to the keys, and second one to the whole object
var req = { 'body' : {
'firstname':'john',
'middlename':'matrix',
'lastname':'smith',
'test' :'jesus'}
};
var targets = ['firstname' , 'middlename', 'lastname'];
for(var key in req['body']){
console.log('the key is '+ key + ' the value is ' + req['body'][key]);
}
When you want to set a dynamic key in an object, you have to use brackets, like this:
const obj = {
[keyName]: null,
};
So, in your example, you have to fix the syntax error like this:
console.log({
[Object.keys(req.body)[i]]: req.body[Object.keys(req.body)[i]]
});
The below builds an object foo by iterating through the targets array and searching for the properties it cares about in req.body using Object.prototype.hasOwnProperty(key), which should be an O(1) check, then prints foo:
var req = { 'body' : {
'firstname':'john',
'middlename':'matrix',
'lastname':'smith',
'test' :'jesus'}
};
var targets = ['firstname' , 'middlename', 'lastname'];
let foo = {};
for (let key of targets) {
if (req.body.hasOwnProperty(key))
foo[key] = req.body[key];
}
console.log(foo);
Also, if you decide to introspect an Object's properties, you can use for..in looping. For iterating over Arrays, you can use for..of.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
I am creating a dynamic javascript object to query from the mongodb, and my code as follows,
_.each(separatedFilter, function (str) {
const filter = str.split('=');
console.log('filter is', JSON.stringify(filter));
if (filter[1] && filter[1].trim() !== '') {
var key = `${filter[0]}`;
var obj = {};
obj[key] = filter[1];
if (key = 'date.start:{$gte') {
key = '"date.start":{"$gte"';
}
if (key = 'date.end:{$lt') {
key = '"date.end":{"$lt"';
}
query.push(obj);
}
});
the above code creates a object as follows,
{ '$and':
[ { name: [Object] },
{},
{ '"date.start":{"$gte"': '2016-12-18T18:30:00.000Z',
'"date.end":{"$lt"': '2016-12-18T18:30:00.000Z' }
] }
in the above object i could see ' at the start and end of date.start and date.end. whereas i just want it to be,
{ '$and':
[ { name: [Object] },
{},
{ "date.start":{"$gte": '2016-12-18T18:30:00.000Z',
"date.end":{"$lt": '2016-12-18T18:30:00.000Z' }
] }
You cannot define a value (the nested object) via a key, nor can you partially define an object with a key (i.e. $gte) but without a value.
A fix would look something like this:
if (key === 'date.start:{$gte') {
obj['date.start'] = { '$gte' : null };
}
if (key === 'date.end:{$lt') {
obj['date.start'] = { '$lt' : null };
}
obj[key] = filter[1];
This assumes that null will be replaced with the appropriate timestamps somewhere else in the program and then you can serialize that object to a string before sending the query.
Explanation
These lines have a number of problems:
if (key = 'date.start:{$gte') {
key = '"date.start":{"$gte"';
}
if (key = 'date.end:{$lt') {
key = '"date.end":{"$lt"';
}
They are inserting quotes into the key for some reason. Probably just a mistake.
They are assigning to key within the conditional statement, rather than doing a comparison. This will have the effect of always executing the code within the if block, because the string being assigned and returned is always truthy.
They come after the key and its value are already assigned to the object via obj[key] = filter[1]. Since the assignment has already run by the time the if statements do, they have no chance to affect the key that is used in the assignment.
Also, this line:
var key = `${filter[0]}`;
Can be simplified, as it is the same as:
var key = filter[0];
Or even better with let and destructuring:
let [key] = filter;
Im trying to get indexOf of a object after its pushed inside a array.
This is not returning the same value back as i do indexOf whenever objext is allready in the array.
SCENARIO
var arr = [];
setInterval(function() {
var path = { one: "f00"};
if (typeof path !== "undefined") {
if (arr.indexOf(path) === -1) {
console.log("Not Exists!!")
arr.push(path)
} else {
console.log("Exists!!")
}
}
console.log(arr)
}, 2000)
What is the different between the working of
The issue is that JavaScript doesn't do a deep compare of objects, so it doesn't recognize them as the same.
var a = { name: 'foo' }
var b = { name: 'foo' }
a === b // false
However, since you have access to the object before the insert, you can save a reference to it, and then search for that reference:
var arr = []
var obj = { path: 'foo' }
arr.push(obj)
arr.indexOf(obj) // 0
This is because indexOf uses the strict equality === comparison. So in this case, the references to obj and the object at arr[0] are the same.
Edit
Based on your changed question, here is a way to write your function to do what you want:
var arr = [];
function findAdnSet(obj) {
var index = arr.indexOf(obj);
if (index !== -1) {
return index;
} else {
arr.push(obj);
return arr.length - 1; // No reason to use indexOf here, you know the location since you pushed it, meaning it HAS to be the last element in the array
}
}
var path = { name: 'foo' };
findAndSet(path);
A more robust option than using indexOf since your function might not always have a good reference available is to use find/findIndex:
var arr = [];
function findAndSet(obj) {
var index = arr.findIndex(function(item) {
if (item.name === 'foo') {
return true;
}
});
if (index) { // findIndex returns `undefined` if nothing is found, not -1
return index;
} else {
arr.push(obj);
return arr.length - 1;
}
}
// You don't need a reference anymore since our method is doing a "deep" compare of the objects
findAndSet({ name: 'foo' });
The first time you do indexOf you push and search for the object 'path' so it is found. The second time you create an object and add push it to the array, and then search for another new object (which happens to have the same values), but since it is not the same object that you pushed it is not found.
In javascript, I want to select a certain property by it's name, which is stored in a string. I know that window[someString] is the way to go. It works when someString = "somevariable", but unfortunately, my program will also have strings such as someobject.someproperty. This does not work.
So the question is, given code
someString = "one.two.three";
one = {
two: {
three: "This is the value that I want to get"
}
};
// window[someString] does not work.
, how can I get the value of one.two.three using the value of someString, without using eval?
Use split and make a recursive method
var someString = "one.two.three";
var keys = someString.split('.');
one = {
two: {
three: "This is the value that I want to get"
}
};
function getinnerProperty(object, keys) {
var key = keys.shift();
if (keys.length) {
var nestedObject = object[key];
return getinnerProperty(nestedObject, keys);
} else {
return object[key];
}
}
console.log(getinnerProperty(window, keys));
You can write a function that uses split and iteratively traverses the object tree:
var someString = "one.two.three";
var one = {
two: {
three: "This is the value that I want to get"
}
};
function getValue(keyStr) {
var keys = keyStr.split('.');
var result = global;
for (var i = 0; i < keys.length; i++) {
result = result[keys[i]];
}
return result != global ? result : undefined;
}
getValue(someString);
var arr = [{
key: "key1", value: "z"
}, {
key: "key2", value: "u"
}, {
...
}];
How to check whether my key:"key1" exists already or not. If it does not exist, i need to add the key in ma array.
if(arr.hasOwnProperty("key1")){
arr.unshift({key:"key1", value:"z"});
}
To make it easier you should store your data thusly:
var map = {
"key1": "z",
"key2": "u"
};
Then you can do your check and if your keys don't conflict with any existing properties on the object and you don't need null values you can make it easier.
if (!map["key1"]) {
map["key1"] = "z";
}
If you really need the full object (yours is after all just an example), I would store the object as the value of the key, not just store the objects in the array. That is, make it a map, not an array.
Since you've got an Array filled with Objects, you need to do it like:
(ES3)
function lookup( name ) {
for(var i = 0, len = arr.length; i < len; i++) {
if( arr[ i ].key === name )
return true;
}
return false;
}
if( !lookup( 'key1' ) ) {
arr.push({
key: 'key1',
value: 'z'
});
}
You could use the ECMAScript 5 filter method to remove elements from the array if they do not pass your test. If the resulting array has no elements, you know that there were none with your value:
if(!arr.filter(function(elem) {
return elem.key === "key1";
}).length) {
arr.push({ key: "key1", value: "z" });
}
If you want it to work in older browsers you would need to use a shim to make sure Array.prototype.filter is defined.
var key;
for(var i = 0; i < arr.length; i++)
{
if(arr[i].key == "key1")
{
key = arr[i];
break;
}
}
if(typeof (key)=='undefined') //for if the value is 0 as int
{
key = {
key: "key1", value: "aaa"
};
arr.push(key);
}
You can check both arrays and objects to see if an array key or object property exists or not with this. It's very useful, and it is used the same way for checking both types.
/**
* Check if an array key or object property exists
* #key - what value to check for
* #search - an array or object to check in
*/
function key_exists(key, search) {
if (!search || (search.constructor !== Array && search.constructor !== Object)) {
return false;
}
for (var i = 0; i < search.length; i++) {
if (search[i] === key) {
return true;
}
}
return key in search;
}
Usage:
As an array
key_exists('jared', ['jared', 'williams']); //= true
As an object
key_exists('jared', {'jared': 'williams'}); //= true
Below are two, more explicit, versions of #jAndy's accepted answer.
I made the first version for myself so I could understand the logic better and added the following:
if the key does exist, increment the count property of the matched
object, otherwise create a new object with a count of 1.
In the second version, I realised I would prefer my arrayOfObjects variable to be an object, so that later I could specifically target values rather than looping over the array till I got a match, and then getting the relevant object value. So that version uses an object instead of an array of objects.
Version 01 - An array of objects
// based on: https://stackoverflow.com/a/9177103/1063287
// the original array of objects
var arrayofObjects = [{
id: "CY01",
count: 1
},
{
id: "CY33",
count: 5
},
{
id: "CY55",
count: 8
}
];
// show the array in the interface
$(".before").text(JSON.stringify(arrayofObjects));
// define lookup function (must have access to arrayofObjects)
function lookup(key_to_check) {
// for each object in the array of objects
for (var i = 0; i < arrayofObjects.length; i++) {
// if the object key matches the key to check
if (arrayofObjects[i]["id"] === key_to_check) {
// return true with index of matching object
var returnObject = {};
returnObject["exists"] = true;
returnObject["index"] = i;
return returnObject;
}
}
// if the above loop has not already returned a value
// return false
var returnObject = {};
returnObject["exists"] = false;
return returnObject;
}
// on click, check whether the key exists
$(document).on("click", ".run", function() {
var key_to_check = $(".key_to_check").val();
$(".checking").text(key_to_check);
var returnObject = lookup(key_to_check);
// if key to check doesn't exist add it
if (returnObject["exists"] === false) {
console.log("key doesn't exist, adding object");
arrayofObjects.push({
id: key_to_check,
count: 1
});
} else if (returnObject["exists"] === true) {
// else if it does exists, increment the relevant counter
console.log("key does exist, incrementing object count value");
var index = returnObject.index;
arrayofObjects[index].count += 1;
}
$(".after").text(JSON.stringify(arrayofObjects));
});
body {
font-family: arial;
font-size: 14px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>enter an existing or non-existing key and click run.</p>
<p>if existing, increment count, otherwise create new object with count of 1.</p>
<input class="key_to_check"><button class="run">run</button>
<br><br>
<div>array of objects - before: <span class="before"></span> </div>
<div>checking:<span class="checking"></span></div>
<div>array of objects - after: <span class="after"></span></div>
Version 02 - An object
// based on: https://stackoverflow.com/a/9177103/1063287
// the original object
var myObject = {
"CY01": 1,
"CY33": 5,
"CY55": 8
};
// show the object in the interface
$(".before").text(JSON.stringify(myObject));
// define lookup function (must have access to myObject)
function lookup(key_to_check) {
// for each property in the object
for (key in myObject) {
// if the key matches the key to check
if (key === key_to_check) {
// return true
return true
}
}
// if the above loop has not already returned a value
// return false
return false
}
// on click, check whether the key exists
$(document).on("click", ".run", function() {
var key_to_check = $(".key_to_check").val();
$(".checking").text(key_to_check);
var returnObject = lookup(key_to_check);
// if key to check doesn't exist add it
if (returnObject === false) {
console.log("key doesn't exist, adding object");
myObject[key_to_check] = 1;
} else if (returnObject === true) {
// else if it does exists, increment the relevant counter
console.log("key does exist, incrementing object count value");
myObject[key_to_check] += 1;
}
$(".after").text(JSON.stringify(myObject));
});
body {
font-family: arial;
font-size: 14px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>enter an existing or non-existing key and click run.</p>
<p>if existing, increment count, otherwise create new property with count of 1.</p>
<input class="key_to_check"><button class="run">run</button>
<br><br>
<div>my object - before: <span class="before"></span> </div>
<div>checking:<span class="checking"></span></div>
<div>my object - after: <span class="after"></span></div>