Constructing array of objects programmatically - javascript

Say I want the object to be something like this:
var Book = {
title: "the catcher in the rye",
price: "80.98",
characters: [{name: "holden caulfield", age: 16, height:"6.2"},
{name: "phoebe caulfield",age:13, height: "5"}]
};
EDITED
question:
characters array is built by adding a character one by one. How can do this while making sure that name, age and height properties are defined as above.
Something to the effect of?
Book.characters.add({name: "phoebe caulfield",age:13, height: "5"});
I would like to be able to define this programmatically, ie add properties to the object rather than define it like this.
Is this possible?

You can do it in dynamic code (rather than a static declaration) like this:
var Book = {};
Book.title = "the catcher in the rye";
Book.price = "80.98";
Book.characters = [];
Book.characters.push({name: "holden caulfield", age: 16, height: "6.2"});
Book.characters.push({name: "phoebe caulfield", age: 13, height: "5"});

Do you mean like this?
var Book = {}; // empty object
Book.title = "the catcher in the rye";
Book.price = 80.98;
Book.characters = [];
var character = {
"name": "holden caulfield",
"age": 16,
"height": 6.2
};
Book.characters.push(character);

var Book={};
Book.title="the catcher in the rye";
Book.price="80.98";
var characters=[];
characters.push({name: "holden caulfield", age: 16, height:"6.2"});
characters.push({name: "phoebe caulfield",age:13, height: "5"});
Book.characters=characters;
...etc.

It certainly is! Javascript is a completely dynamic language - if you want a new property on an object, just set it!
e.g.
var myObject = {}; // empty object
myObject.myProperty = 5; // creates the new property and sets it to 5.
myObject.nestedObject = { prop1: 6, 'long-property-name': 'lolcats' };

I think you're looking for a JSON stringifier:
http://www.json.org/js.html
This will allow you to create your object:
var myobj = { };
myobj.myprop = "value";
alert(JSON.stringify(myobj));

using the map function is the easiest way I've found to build an array of objects. The snippet below, constructs the objet you want in just 2 statements:
var Book = {
title: "the catcher in the rye",
price: 80.98
};
Book.characters = [6.2, 5].map(el => {
return {
name: 'caulfield', age: 14, height: el
};
});
// Output
JSON.stringify(Book);
{
"title": "the catcher in the rye",
"price": 80.98,
"characters": [
{ "name":"caulfield", "age":14, "height":6.2 },
{ "name":"caulfield", "age":14, "height":5 }
]
}

Related

Loop over an object

I'm decoding an object and so far I got it working. Let's say I have this object:
var person = [{
firstname: "Mike",
lastname: "123ñññ"
age: 20
}]
So in order to decode &ntilde and render ñ, I'm simply doing this:
new DOMParser().parseFromString(person[0].lastname, "text/html").documentElement.textContent;
and this will render the value
ñññ
which is what I want, so it will look like this:
lastname: "ñññ"
However, the issue that I'm facing is that I need to decode values for each property in the object because I may get those special characters for firstname or other properties. So my question is how to decode property values on an object assuming that the object may look like this:
var person = [{
name: "Mike",
lastname: "123ñññ"
age: 20,
employeer: {
name: 'ABC Company ñê',
supervisors:[
{
name: 'Steveä',
code: 'è468'
}
]
}
}]
NOTE:
I don't need help on decoding that values of each property on my object, since I'm already doing that, I just need to come up with a recursive function that will do that on a nested object
I think a recursive decode using DOMParser is a good idea. Here's an in-place transformer. Perform a deep copy first and then transform in-place if you prefer.
var person = [{
name: "Mike",
lastname: "123ñññ",
age: 20,
employer: {
name: 'ABC Company ñê',
supervisors: [
{
name: 'Steveä',
code: 'è468'
}
]
}
}];
console.log(person);
function htmlDecode(input)
{
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
function fix(obj) {
for (let prop in obj) {
switch (typeof obj[prop]) {
case 'object':
fix(obj[prop]);
break;
case 'string':
obj[prop] = htmlDecode(obj[prop]);
break;
}
}
}
fix(person);
console.log(person);
in functional languages there are libraries to recursively walk tree scructures. In clojure there is the zipper and walk for example.
you could write it yourself but it will quickly get complicated so I suspect using JSON.stringify + parse would give you what you need. Both functions take second argument that's replacer and reviver respectively that allow you to intercept the transformations and alter the values.
Here is example from the official documentation:
function replacer(key, value) {
// Filtering out properties
if (typeof value === 'string') {
return undefined;
}
return value;
}
var foo = {foundation: 'Mozilla', model: 'box', week: 45, transport: 'car', month: 7};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'
Try this:
function decodeObject(obj){
if(typeof obj == 'object'){
var text = JSON.stringify(obj),
div = document.createElement('div');
div.innerHTML = text;
obj = JSON.parse(div.childNodes[0].nodeValue);
}
return obj;
}
var person = decodeObject([{
name: "Mike",
lastname: "123ñññ",
age: 20
}]);
console.log(person);

Javascript two-way reference issue

I am very confused about Javascript referencing. I understand when referencing an object, there is a reference made. Changing the parent changes the copy and vice versa.
What I am confused about is when reassignment changes are made to the parent, the copy retains everything. See my example
let tester = {
"hello": "how are you",
"myArrayHere": [
{ "id": 1, "name": "me" },
{ "id": 2, "name": "you" },
{ "id": 3, "name": "them" },
]
};
var something = tester.myArrayHere.find(x => x.name === "you");
console.log(something);
console.log("--------");
something.id = 99;
console.log(something);
console.log("--------");
console.log(tester.myArrayHere[1]);
console.log("--------");
tester.myArrayHere[1].id = 88;
console.log(something);
console.log("--------");
tester.myArrayHere[1] = {};
console.log(tester.myArrayHere[1]);
console.log("--------");
console.log(something)
If you run that example, something on the last line, still has the entire object, even though two lines above, its reference was re-assigned.
There are other examples of this, such as when you delete things off the parent, etc. If this is purely a reference and not a copy (such as with primitive types) why are these changes not affecting it as it should?
The something variable simply refers to a (pre-defined) object stored in the memory. It's value is the returned value (a referral to an object) of the Array#find method. Variables do not observe any specific path (e.g. tester.myArrayHere[1]), they are not observers. In other words, in this case, JavaScript interpreter doesn't care/remember how you get the object/value before the assignment.
> var a, b; a = b = {};
> a === b
true
> a = {}
> a === b
false
After executing tester.myArrayHere[1] = {};, the second element of the array refers to a new object. The something variable still refers to the old object.
Please check the explanation in a snippet
let tester = { // tester is a link to a object (not an object itself) in memory
"hello": "how are you",
"myArrayHere": [ // tester.myArrayHere is a link to a object (not an object itself) in memory
{ "id": 1, "name": "me" },
{ "id": 2, "name": "you" }, // tester.myArrayHere[1] is a link to a object (not an object itself) in memory
{ "id": 3, "name": "them" },
]
};
var something = tester.myArrayHere.find(x => x.name === "you"); // something now is the same link to the object { "id": 2, "name": "you" }, but not an object itself tester.myArrayHere[1] will be === something link is eqaul to link
console.log(something);
console.log("--------");
something.id = 99;
console.log(something);
console.log("--------");
console.log(tester.myArrayHere[1]);
console.log("--------");
tester.myArrayHere[1].id = 88;
console.log(something);
console.log("--------");
tester.myArrayHere[1] = {}; // now tester.myArrayHere[1] becomes a link to a new object, { "id": 2, "name": "you" } is still in a memory and something is link to it
console.log(tester.myArrayHere[1]);
console.log("--------");
console.log(something)
Its best to conceptualize the code you posted as "having a direct shortcut to the nested field"
const joe = { // (A) joe is an object
id: 42,
name: 'joe',
hobbies: [ // (B) hobbies is an Array, a reference type
'surfing',
'videogames'
]
}
// (C) this variable has no idea that it is part of person object from (A)
const cloneHobbies = joe.hobbies
cloneHobbies.push('boxing')
console.log('***JOE***', joe) // Joe now has a new hobby: boxing
// It also works the other way; Joe's hobbies become someone else's
joe.hobbies.push('karate')
console.log("***CLONE'S HOBBIES***", cloneHobbies) // now has 'karate'
Hope this helps you conceptualize the code.
Cheers,

Clone a object only with few properties

Is there a way to clone an object with only few properties of the object in JS?
For example..
var Person = {
name: "Bob",
age: 32,
salary: 20000
};
I have to create another person object with just the name and age property so that it will look something like this :
var clonedPerson = {
name: "Bob",
age: 32
};
I could do a deep clone of the object and delete. But I wanted to know if there are better ways to do it.
Using the latest ES6, you can achieve this by the following code..
const Person = {
name: "Bob",
age: 32,
salary: 20000
};
const { salary , ...clonedPerson } = Person
console.log(clonedPerson)
More simple?
var Person = {
name: "Bob",
age: 32,
salary: 20000
};
var ClonedPerson = jQuery.extend({}, Person);
delete ClonedPerson.salary;
console.log(JSON.stringify(Person));
console.log(JSON.stringify(ClonedPerson));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
an alternative approach using Array member methods:
var clone = Object.keys(Person) // convert to an Array of Person keys
.filter(function(key){return ["salary"].indexOf(key) == -1;}) // exclude key salary
.reduce(function(clone, current){clone[current] = Person[current]; return clone;}, {}); // convert back the array to a cloned literal object

(javascript) Is it possible to split an array of different object types into multiple arrays of one object type

So I have an array that contains objects with different attributes and I want to know how I can make multiple arrays with objects with the same attributes of the whole array.
I want to go from this
[
{name:”test”, place:”country”},
{name:”walkAndEat”, Long=100,Lat:15,Location:”place name”},
{name:”test2”,place:”Europe”}
]
To
[
{name:”test”, place:”country”},
{name:”test2”,place:”Europe”}
]
[
{name:”walkAndEat”, Long:100,Lat:15,Location:”place name”}
]
If you see objects being equal as having the same properties, you can keep the keys as (stringified) indices in a collection object and check if a properties-key already exists:
var arrcoll = {};
function add(o){
var keys = JSON.stringify(Object.keys(o).sort());
var arr = arrcoll[keys];
if(arr)
arr.push(o);
else
arrcoll[keys] = [o];
return arr;
}
This can be done on the fly or on a pre existing array as shown in this Fiddle
Suppose you have a list of objects that have different properties like so:
var placesOrPeople = [
{ name: 'Seymour Skinner', occupation: 'Principal' },
{ name: 'Kwik-E-Mart', lat: 23, long: 100 },
{ name: 'Sideshow Bob', occupation: 'Comic Foil' },
{ name: 'Flaming Tyre Yard', lat: 12, long: 88 },
{ name: 'Joe Quimby', occupation: 'Mayor' }
];
And you want them sorted into separate lists like so:
places = [
{ name: 'Kwik-E-Mart', lat: 23, long: 100 },
{ name: 'Flaming Tyre Yard', lat: 12, long: 88 }
];
people = [
{ name: 'Seymour Skinner', occupation: 'Principal' },
{ name: 'Sideshow Bob', occupation: 'Comic Foil' },
{ name: 'Joe Quimby', occupation: 'Mayor' }
];
You can use the built-in Array.filter command like so:
var places = placesOrPeople.filter(function(currentPlaceOrPerson) {
if (currentPlaceOrPerson.occupation !== undefined) {
// it must be a person, since locations don't have occupations
return true;
} else {
return false;
}
});
var people = placesOrPeople.filter(function(currentPlaceOrPerson) {
if (currentPlaceOrPerson.lat !== undefined && currentPlaceOrPerson.long !== undefined) {
// it must be a place, since people don't have co-ordinates
return true;
} else {
return false;
}
});
Javascript Objects are not set types, they are dynamic, meaning you can change them during execution.
JavaScript is a loosely typed or a dynamic language. That means you don't have to declare the type of a variable ahead of time. The type will get determined automatically while the program is being processed. That also means that you can have the same variable as different types:
var anything = arrayOfAnyOtherType[0];
is valid... If you loop your source array and populate it, you can define any behavior to each object

Complex C# object

I am used to making JavaScript objects like below but what would be the fastest way of doing the same with C#? It is just static data that will be serialized for a post that will not change. In the past with C# I would create classes and lists for everything but in this scenario I just need to send some practice data. Any help would be appreciated
var data = {
"dealer": {
"keyId": "vfase32sd",
"name": "mark"
},
"seller": [
{
"email": "email#email.com",
"active":false
}
],
"state": [
"TN",
"TX"
]};
See Object and Collection Initializers
Object initializer with Anonymous types
Although object initializers can be used in any context, they are especially useful in
LINQ query expressions. Query expressions make frequent use of
anonymous types, which can only be initialized by using an object
initializer, as shown in the following declaration.
var pet = new { Age = 10, Name = "Fluffy" };
For example:
var data = new
{
dealer = new
{
keyId = "vfase32sd",
name = "mark"
},
seller = new[] {
new {
email= "email#email.com",
active= false
}
},
state = new[]{
"TN",
"TX"
}
};
The rule for converting that js object to c# object is simple:
"x": will be x=
{} will be new {}
[] will be new []{}
Values remain untouched
You can use dynamic typing feature of C#
var data = new
{
dealer = new
{
keyId = "vfase32sd",
name = "mark",
},
seller = new[]
{
new
{
email = "email#email.com",
active = false
}
},
state = new []
{
"TN",
"TX"
}
};

Categories