tested keys inside JavaScript object for API - javascript

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

Related

Javascript Loop object and manipulate

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

Select global variable by string, including sub-properties

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

Javascript array within JSON Object

I'm trying to achieve this structure (a JSON Object with an array inside):
var data = {
page : 'hello',
rows: [
{
column: 'two'
}
]
}
But i'm failing miserable, trying various methods, this is my work in progress code:
var data = new Array();
data['settings'] = [];
var i = 0;
var inputName, value;
for (i; i < inputs.length; i++){
inputName = $(inputs[i]).attr('name');
value = $(inputs[i]).val();
data['settings'][inputName] = value;
}
data['page_id'] = page_id;
So i know the variable names are not the same as the desired example but you get the general gist! At the moment, its just making data an empty array. But i need to make it a JSON object with the idea to send it to a server.
What you've quoted is a JavaScript object with a JavaScript array in it, no JSON* in sight.
To create it, I don't think you want an array at all, just an object with a nested object:
var data = {
settings: {},
page_id: page_id
};
var i, input;
for (i = 0; i < inputs.length; i++){
input = $(inputs[i]);
data.settings[input.attr('name')] = input.val();
}
That works because JavaScript objects are maps of name/value pairs. You can refer to a property of an object using dotted notation and a literal property name:
x = obj.foo;
...or using bracketed notation and a string name:
x = obj["foo"];
In the latter case, you can use any expression you like for the string, so for instance:
x = obj["f" + "o" + "o"];
JavaScript also has literal object initializers, which you can use to create an object with properties already on it:
obj = {foo: "bar"};
That creates an object with a property called foo with the value "bar" and assigns the object to the obj variable.
So looking again at the code block above:
We create an object with the properties settings and page_id. settings is initialized with a blank object; page_id is initialized with the value of the page_id variable.
Then we loop through your inputs and add properties to settings using the name of each input, setting the value of the property to be the value of the input.
So let's assume we have
<input name="oneField" value="bar">
<input name="anotherField" value="bang">
<input name="yetAnotherField" value="cool">
...and let's assume page_id is 3.
We'll end up with this structure in the object referenced by the data variable:
{
settings: {
oneField: "bar",
anotherField: "bang",
yetAnotherField: "cool"
},
page_id: page_id
}
* JSON is a textual notation. When you're writing things like var data = { ... }; in code, you're just using JavaScript. JSON is a subset of JavaScript literal syntax that's designed to be easy to parse, so for instance it's handy for storing arbitrary complex data in data stores, or for retrieving data from a server. You retrieve the string, which contains the data, and then parse that string to build up an object structure in memory.
var data = {};
data['settings'] = {};
var i = 0;
var inputName, value;
for (i; i < inputs.length; i++){
inputName = $(inputs[i]).attr('name');
value = $(inputs[i]).val();
data['settings'][inputName] = value;
}
data['page_id'] = page_id;
This will give you such result like below:
{
page_id: 12345,
setting: { foo: 'one', bar: 'two'}
}
Both [] and new Array() are used to initialize an array; what you're after (as you're trying to map keys to values), are objects; which are initialized using either {} or new Object().
var data = {};
data['settings'] = {};
var i = 0;
var inputName, value;
for (i; i < inputs.length; i++){
inputName = $(inputs[i]).attr('name');
value = $(inputs[i]).val();
data['settings'][inputName] = value;
}
data['page_id'] = page_id;
To help you with your syntax, square bracket notation is only needed if the member you're looking up is a variable, or if the key contains reserved words or special characters (spaces etc). Otherwise, you can use dot notation;
var data = {};
data.settings = {};
var i = 0;
var inputName, value;
for (i; i < inputs.length; i++){
inputName = $(inputs[i]).attr('name');
value = $(inputs[i]).val();
data.settings[inputName] = value;
}
data.page_id = page_id;
When using object literal syntax ({}) to construct an object, you are allowed to define members on the object as well. It's also more common to declare your looping variable within the for loop rather than outside.
var data = {
settings: {}
};
var inputName, value;
for (var i=0; i < inputs.length; i++){
inputName = $(inputs[i]).attr('name');
value = $(inputs[i]).val();
data.settings[inputName] = value;
}
data.page_id = page_id;

Set of objects in javascript

I'd like to have a set of objects in Javascript. That is, a data structure that contains only unique objects.
Normally using properties is recommended, e.g. myset["key"] = true. However, I need the keys to be objects. I've read that Javascript casts property names to strings, so I guess I can't use myset[myobject] = true.
I could use an array, but I need something better than O(n) performance for adding, finding and removing items.
It needs to be able to tell objects apart by reference only, so given:
var a = {};
var b = {};
then both a and b should be able to be added, because they're separate objects.
Basically, I'm after something like C++'s std::set, that can store Javascript objects. Any ideas?
ES6 provides a native Set:
let s = new Set();
let a = {};
let b = {};
s.add(a);
console.log(s.has(a)); // true
console.log(s.has(b)); // false
Here's a mad suggestion ... key it on the result of JSON.stringify(object)
It's not possible for all objects, but if your object has a .toString() method implemented, it is:
var x = {toString: function(){ return 'foo'; }};
var y = {toString: function(){ return 'bar'; }};
var obj = {};
obj[x] = 'X';
obj[y] = 'Y';
console.log(obj);
// { foo: 'X', bar: 'Y' }
If you want to make this easier, make it a class:
function myObj(name){
this.name = name;
}
myObj.prototype.toString = function(){ return this.name; }
var obj = {};
obj[new myObj('foo')] = 'X';
obj[new myObj('bar')] = 'Y';
I'm answering my own question, but I came up with an alternative solution I thought was interesting and thought it would be useful to share it.
cwolves' answer gave me an idea. Providing an object's toString() method uniquely identifies the instance, properties of an object can be used to store a set of objects. Essentially, to store object x, you can use items[x.toString()] = x;. Note that the value is the object itself, so then the set of objects can be extracted by looking at all item's properties and dumping all the values in to an array.
Here's the class, which I call ObjectSet, in full. It requires objects are uniquely identified by their toString() method, which is OK for my purposes. add, remove and contains should all run in better than O(n) time - whatever javascript's property access efficiency is, which hopefully is either O(1) or O(n log n).
// Set of objects. Requires a .toString() overload to distinguish objects.
var ObjectSet = function ()
{
this.items = {};
this.item_count = 0;
};
ObjectSet.prototype.contains = function (x)
{
return this.items.hasOwnProperty(x.toString());
};
ObjectSet.prototype.add = function (x)
{
if (!this.contains(x))
{
this.items[x.toString()] = x;
this.item_count++;
}
return this;
};
ObjectSet.prototype.remove = function (x)
{
if (this.contains(x))
{
delete this.items[x.toString()];
this.item_count--;
}
return this;
};
ObjectSet.prototype.clear = function ()
{
this.items = {};
this.item_count = 0;
return this;
};
ObjectSet.prototype.isEmpty = function ()
{
return this.item_count === 0;
};
ObjectSet.prototype.count = function ()
{
return this.item_count;
};
ObjectSet.prototype.values = function ()
{
var i, ret = [];
for (i in this.items)
{
if (this.items.hasOwnProperty(i))
ret.push(this.items[i]);
}
return ret;
};
I used Map, solved my case
const objectsMap = new Map();
const placesName = [
{ place: "here", name: "stuff" },
{ place: "there", name: "morestuff" },
{ place: "there", name: "morestuff" },
];
placesName.forEach((object) => {
objectsMap.set(object.place, object);
});
console.log(objectsMap);
For what you're trying to do (sets of objects), there is no native Javascript implementation. You would have to implement this on your own. One way to do this would be to implement a hashing function for your objects. The backing data-type of the set would be an associative array, where the key of the array is the value you get from calling the object's hash function, and the value of the array is the object itself.
Of course, this doesn't address the issue that you highlighted, so you will need to take equality into account as well (implement an equals function perhaps)?
Instead of making the hash function a property of the object itself, you can have a standalone hash function that takes in an object as input and generates a hash value (presumably by iterating over its properties).
Using this method you should be able to get O(1) for insertion, searching, and removing (not counting the order of the hash function, which shouldn't be any worse than O(n), especially if you are iterating over its properties to create your hashed value).
ECMAScript6 Set should behave like that:
Standard: http://www.ecma-international.org/ecma-262/6.0/#sec-set-o-p-v-throw
Unofficial ES6 cheat sheet: https://github.com/lukehoban/es6features#map--set--weakmap--weakset
Working example on Firefox 32 (but not implemented in Chromium 37):
if (Set) {
var s = new Set()
var a = {}
var b = {}
var c = {}
s.add(a)
s.add(b)
s.add(b)
assert(s.size === 2)
assert(s.has(a))
assert(s.has(b))
assert(!s.has(c))
}
This is not surprising since {} != {}: equality compares object addresses by default.
A module that implements it for browsers without support: https://github.com/medikoo/es6-set
Javascript Set's don't do deep object comparison.
Using lodash, this is a unique array with deep object comparison:
const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.uniqWith(objects, _.isEqual);
Just typed this up, it's only briefly tested:
var Set = function Set()
{
var list = [];
var contains;
this.contains = contains = function(x) {
return list.indexOf(x) >= 0;
}
var put;
this.put = put = function(x) {
if (!contains(x))
list.push(x);
return this;
}
var remove;
this.remove = remove = function(x)
{
var idx = list.indexOf(x);
if (idx >= 0)
list.splice(idx,1);
return this;
}
var all;
this.all = all = function()
{
return list.concat();
}
return this;
}
It seems that the inner call of function works when prefixed with this.
Exemple:
var put;
this.put = put = function(x) {
if (!this.contains(x))
list.push(x);
return this;
}
Please use this code as a reference.
const fruits = [
{name: 'apple', price: 100},
{name: 'apple', price: 100},
{name: 'orange', price: 200},
{name: 'grapes', price: 300}
];
const hasFruitDuplicated = () => {
const duplicatedDeleteFruits = fruits.filter((fruit, index) =>
fruits.findIndex(item => item.name === fruit.name && item.price === fruit.price) === index
);
return duplicatedDeleteFruits;
};
Given an array of the following type:
Array<{ foo: T1, bar: T2 }>
You can build a corresponding dictionary of type:
{ [foo: T1]: Set<T2> }
The look-up for { foo: fooValue, bar: barValue } can be performed as follows:
if (fooValue in dictionary && dictionary[fooValue].has(barValue))
This way we can build what would be an ObjectSet<T1, T2>
.
If you now have three elements, you can build the following dictionary:
{ [foo: T1]: ObjectSet<T2, T3> }
and extend your ObjectSet to any number of properties by induction.
That is assuming your types can be used as index signatures.

JavaScript object - add property without using eval?

I have a JavaScript object that I'd like to add some properties to, but I don't know what the names of the properties are until runtime.
Can I do this without using eval? If so, how?
var get_params = new Object();
var params = {'name':'john', 'age':'23'}; //actually not known until runtime
for (var i=0, len=params.length; i<len; ++i ){
get_params.p[0] = p[1]; //How can I set p[0] as the object property?
}
}
Since your code example has a malformed array, I will include 2 variations.
Variation 1 (params is an actual object and not an array):
var get_params = {}; // prefer literal over Object constructors.
var params = {'name':'john', 'age':'23'}; // #runtime (as object literal)
for (var key in params){
if(params.hasOwnProperty(key)) { // so we dont copy native props
get_params[key] = params[key];
}
}
Variation 2 (param is an array containing objects):
var get_params = {}; // prefer literal over Object constructors.
var params = [{'name':'john'},{'age':'23'}]; // #runtime (as array literal)
for(var i=0,param;param=params[i];i++) {
for (var key in param){
if(param.hasOwnProperty(key)) {
get_params[key] = param[key];
}
}
}
Enjoy.
You can access objects via object['someKey'] as well.
var get_params = {};
var params = [{'name':'john'}, {'age':'23'}];
for (var i=0,len=params.length; i<len; ++i){
for (var p in params[i]) {
if(params[i].hasOwnProperty(p)) {
get_params[p] = params[i][p];
}
}
}
Ok, that's my third version. I think it will do what I understand you to desire. Kind of convoluted however, and there are probably better formats for your dynamic array. If I understand what you want to do correctly, this should work. Basically, it creates the following object:
get_params = {
name: "john",
age: "23"
}

Categories