I'm trying to create an 'anonymous array' but it seems there is no such thing, is there some technique that would allow me to omit the array_of_objects: property from the G: object but keep everything else the same?
Since ECMAScript 2015 (or ES6), this:
{ array_of_objects }
is considered the same as
{ "array_of_objects": array_of_objects }
It's creating a property with that name. If you don't want this property, all you need to do is remove the curly braces:
return { cells: array_of_objects };
Here is the solution (if I understood your question correct)
setup: function() {
var cells = {}; // Better to use [], but nm
for(var x = 0; x< 121; x++) {
cells[x] = {id:x}
}
return { cells: cells }
}
Related
I have a complex object in typescript that i want to be able to change with a single function (I know how hacky this sounds, but its a hobby project). The function takes a value and a path as a rest-parameter. The path can be of any length.
I want to change the property, but so far I've only come up with solutions that lose the reference to the original object, and as such is not a working solution.
I've tried using both whiles and for loops to iterate over the array and "zooming" in on the property. In each case, they lost the reference to the original object and thus didn't mutate it.
I've tried accessing the object directly, with a known length, and that works but its hardcoded to a length and as such isn't a good solution either. In a desperate case, i could make a function like this for each size I'm expecting (it's somewhat limited) but that hurts my pride.
Example
character: Character = {
characteristics: {
0: {
initial: 30,
advances: 15
}
1...
}
}
this.updateProperty(35, characteristics, 0, initial) //Change characteristics.0.initial to be 35 instead of 30
With a for/while loop:
updateProperty(value: string|number,...path: string[]) {
let scope: Object = this.character;
for(let p of path) {
scope = scope[p];
}
scope = value;
console.log(scope);
console.log(this.character);
}
the scope is updated correctly, but the character is not changed
With direct access (Here of length 3)
updateProperty(value: string|number,...path: string[]) {
this.character[path[0]][path[1]][path[2]] = value;
}
Here its updated correctly, but its no longer taking in any length as it will crash if its longer than 3 and break it if shorter than 3
Attempt to access it directly with an array
updateProperty(value: string|number,...path: string[]) {
this.character[path] = value;
}
Gives
ERROR in src/app/character.service.ts(27,20): error TS2538: Type 'string[]' cannot be used as an index type.
Considering your direct access works fine for you, you can try something like:
let character = {
characteristics: {
0 : {
initial: 30,
advances: 15
}
}
}
function updateProperty(value,...path) {
let finalOb, i;
for (i = 0; i < path.length; i ++) {
let tempOb
if (finalOb) {
tempOb = finalOb[path[i]];
} else {
tempOb = character[path[i]];
}
if (tempOb instanceof Array || typeof tempOb !== 'object') {
break;
} else {
finalOb = tempOb;
}
}
finalOb[path[i]] = value;
}
updateProperty(35, 'characteristics', '0', 'initial')
console.log(character)
updateProperty(value: string|number,...path: string[]) {
let scope: Object = this.character;
for(let p of path) {
scope = scope[p];
}
scope = value;
console.log(scope);
console.log(this.character);
this.character = scope; //?
}
I have an object which may or may not have nested objects and properties, and I want to access them using a string. Here's an example...
var obj = {
inside: {
value: 10,
furtherInside: {
value: 100
}
}
// may contain other objects, properties, etc.
};
function getObjProperty(str) {
return eval("obj." + str);
}
getObjProperty("inside.value"); // returns 10
getObjProperty("inside.furtherInside.value"); // returns 100
...But I'd like a solution that doesn't use eval.
How can this be done without using eval? I'm looking for the best/optimal/fastest solution.
How about something like
function getObjectProperty(obj, str) {
var props = str.split('.')
var result = obj;
for(var i = 0; i < props.length; i++)
result = result[props[i]];
return result;
}
This code assumes your strings are always valid and the object passed into getObjectProperty has properties that nest to the level you target, but it avoids eval. You could make it more robust with checks for undefined, but that may be overkill for what you need.
Test code, using your example:
var a = {
inside: {
value: 10,
furtherInside: {
value: 100
}
}
// may contain other objects, properties, etc.
};
console.log(getObjProperty(a, "inside.value")); // prints 10
console.log(getObjProperty(a, "inside.furtherInside.value")); // prints 100
You can use the brackets notation:
var obj = {
inside: {
value: 10,
furtherInside: {
value: 100
}
}
// may contain other objects, properties, etc.
};
alert(obj['inside']['furtherInside']['value']);
Then you may even use string properties like "my property":
var obj = {
"my property": 10
};
obj["my property"];
EDIT:
This is an approach (using brackets notation) to what you are asking for:
String.prototype.getVal = function(elem) {
var segments = this.split('.');
for (var i = 0; i < segments.length; i++) {
elem = elem[segments[i]];
}
return elem;
}
var obj = {
inside: {
value: 10,
furtherInside: {
value: 100
}
}
// may contain other objects, properties, etc.
};
console.log("inside.furtherInside.value".getVal(obj));
console.log("inside.value".getVal(obj));
http://jsfiddle.net/luismartin/kphtqd54
Since this method getVal() is being assigned to the String prototype, you may use it anywhere, and I think the implementation is pretty neat and fast. I hope this approach also helps getting rid of the negative vote :/
This is what I came up with, using some recursiveness...
function getObjProperty(obj, props) {
if (typeof props === 'string') {
if (props.indexOf('.') == -1) {
return obj[props];
} else {
props = props.split('.');
}
}
if (props.length == 1) {
return obj[props[0]];
} else if (props.length > 1) {
var top = props.shift();
return getObjProperty(obj[top], props);
} else {
return obj;
}
}
http://jsfiddle.net/0em2f6k6/
...But it's not as fast as a simple for-loop. http://jsperf.com/0em2f6k6
Although not vanilla JavaScript, another possibility is to use lodash's _.get function: https://lodash.com/docs#get.
_.get(obj, "inside.furtherInside.value");
It essentially does the same as #analytalica 's solution, except using a while loop (see the baseGet function in the lodash code), but it also allows strings or arrays (using the toPath function), and allows you to include a default.
I'm trying to implement a vector object instantiated like below...
var a = new Vector([1,2,3]);
var b = new Vector ([2,2,2]);
...and when I do a math operation I need something like this...
a.add(b); // should return Vector([3,4,5])
...but my code below returns me just an array
function Vector(components) {
// TODO: Finish the Vector class.
this.arr = components;
this.add = add;
}
function add(aa) {
if(this.arr.length === aa.arr.length) {
var result=[];
for(var i=0; i<this.arr.length; i++) {
result.push(this.arr[i]+aa.arr[i]);
}
return result;
} else {
return error;
}
}
Please help me out here. Thank you!
Perhaps it is simpler to extend javascript's native Array, so that there is no need for keeping around an extra Vector.arr property. Here is a simple implementation called for learning purposes that boils down to this, in modern JS:
class Vector extends Array {
// example methods
add(other) {
return this.map((e, i) => e + other[i]);
}
}
// example usage
let v = new Vector(1, 2, 3);
console.log(v.add(v));
This class inherits Array's constructor. Note passing in a single value creates an empty Array of that length and not a length 1 Array. Vector would require a super call in the constructor to inherit exotic Array behavior, such as having a special length property, but this shouldn't be needed for a math vector of fixed length.
You can include fancier constructor behavior here, such as being able to construct from an Array as input.
You need to wrap up your resulting array in a new Vector object:
function Vector(components) {
// TODO: Finish the Vector class.
this.arr = components;
this.add = add;
}
function add(aa) {
if(this.arr.length === aa.arr.length) {
var result=[];
for(var i=0; i<this.arr.length; i++) {
result.push(this.arr[i]+aa.arr[i]);
}
return new Vector(result);
} else {
return error;
}
}
I should note also that you may want to do further reading on creating JavaScript objects, in the area of creating methods (such as your add method) on the prototype of the Vector object. There are many good tutorials out there.
The solution by James looks good but it's a bit old-fashioned in my opinion. Here is a way to solve the problem in modern ES6 Javascript Classes.
class Vector {
constructor(arr) {
this.arr = arr;
}
add(otherVector) {
const oa = otherVector.arr;
if (this.arr.length === oa.length) {
let res = []
for(let key in this.arr) {
res[key] = this.arr[key] + oa[key]
}
return new Vector(res)
}
}
}
Ok, so I've blocked myself in with a stupid move that is now causing conflict with the jQuery library I am using, and well I should say rather is likely breaking more than just that after the reading I have done. Anyway I was attempting to use the following bit:
Array.prototype.contains = function(v) {
for(var i = 0; i < this.length; i++) {
if(this[i] === v) return true;
}
return false;
};
Array.prototype.unique = function() {
var arr = [];
for(var i = 0; i < this.length; i++) {
if(!arr.contains(this[i])) {
arr.push(this[i]);
}
}
return arr;
}
To get the unique values of an array however, this ended up causing a conflict for jQuery in my cause breaks a lot of things, So how can I get around the forbidden yet tasty idea of using prototype? Specifically in this case of needing to the unique values in an array?
A common way to avoid modifying prototypes of native types is static methods:
Array.unique = function( entity ) {
// do your stuff
};
// example call
var unique = Array.unique( [1, 1, 2, 3] );
Or, to take it one step further, even do something like this
var Arrays = Arrays || {};
Arrays.unique = function( entity ) { /* … */ };
This way you are completely separated from the built-in Array.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Easiest way to find duplicate values in a JavaScript array
I am looking to find if two values are the same in an Array. I have written the following code:
function validatePassTimeFields(passtimes) {
var success = true;
var length = passtimes.length;
var hashMap = new Object();
for (var j=0; j<length; j++) {
if(hashMap[passtimes[j].value]==1) {
success = false;
alert("Duplicate Found");
break;
}
hashMap[passtimes[j].value]=1;
}
return success;
}
I am new to Javascript, so I tried using HashMap like to find if there is any duplicate. IS it the best way of finding a duplicate in JavaScript? or I can optimize it?
Your function is already very good, apart from the issue that it only works for arrays with strings or numbers. For a more difficile approach to care also about objects see this answer. I don't think that matters for you as you have an explicit and restricted use case (checking identity by the value property).
However, some points I'd do different:
Don't use the success variable and break from the loop, but just return from the whole function.
Instead of the constructor new Object usually the shortcut object literal {} is used
Instead of setting the values in the hashMap to 1 one might use true; you also could omit the equality operator == and just check for the truthiness of the property. I even would use the in operator.
function validatePassTimeFields(passtimes) {
var length = passtimes.length;
var hashMap = {};
for (var j=0; j<length; j++) {
if (passtimes[j].value in hashMap) {
alert("Duplicate Found");
return false;
}
hashMap[passtimes[j].value] = 1;
}
return true;
}
// You would only need to optimize it if you want to use it elsewhere-
function noduplicates(array){
var next, O= {},
L= array.length;
while(L){
next= array[--L];
if(O[next]) return false;
O[next]= 1;
}
return true;
}
function validatePassTimeFields(passtimes){
if (noduplicates(passtimes)) return true;
alert("Duplicate Found");
return false;
}
It might be worth checking out underscore's implementation of this functionality. If you are just looking to eliminate dupes, you can use _.uniq(), but if you are more interested in just knowing that there are dupes or the pure implementation details, you might enjoy checking out the source of this method, which is very nicely documented.
I know this isn't a direct code answer to the question - there are a few here already so it wouldn't be useful to repeat. But I thought it was worth mentioning as underscore is a great utility library and the source is a great place to learn more about well-written javascript.
It seems that you do not want to find the duplicates, only to see if there are any?
You're pretty close, here's a working function;
var hasDuplicates = function (arr) {
var _store = {};
for (var i = 0; i < arr.length; i++) {
if (typeof _store["_" + arr[i]] !== "undefined") {
return true;
}
_store["_" + arr[i]] = true;
}
return false;
};
The underscores in the associative array are necessary for storing numeric values. The hasDuplicates() function only works objects which have a toString() method.
To check for duplicates;
var yourArray = [1, 5, 7, 3, 5, 6];
if (hasDuplicates(yourArray)) {...