Declare empty es6 Set inside object literal - javascript

I have a JavaScript object:
let component = {
id: comp.id,
name: comp.name,
attributes: {
initial: [
],
final: [
]
}
};
To prevent duplication in initial and final properties I want to use Set instead of array, but how do we declare Set without new operator inside object literal? I want to avoid doing the following if possible:
component.attributes.initial = new Set();
component.attributes.final = new Set();

There is nothing wrong with declaring an empty set inside the object literal:
let component = {
id: comp.id,
name: comp.name,
attributes: {
initial: new Set(),
final: new Set()
}
};

attributes: {
initial: new Set([]),
final: new Set([])
}

You can use any expression as value of a property in an object literal, which includes new Set:
{
initial: new Set(),
final: new Set(),
}

Related

How to work with array of maps in Typescript

I've got a problem with initialize an arrays of map objects in my typescript interface like below:
interface SomeInterface{
id: string,
types: Array<Map<string, number>>;
}
I need to create object with field types as an array which will be hold many of map with string and number. I want this, but i don't know how to add new map into this array.
I try even in this way but it not work and types is still an empty object:
const t: Array<Map<string, number>> = new Array<Map<string, number>>();
const map = new Map<string, number>();
t.push(map.set("test1", 2));
t.push(map.set("test2", 5));
const a: SomeInterface= {
id: "test",
types: t
}
console.log(a);
//{
// "id": "test",
// "types": [
// {},
// {}
// ]
//}
Can someone tell me how to add new map into an typescript array?
thanks for any help!
According to your code I would do something like following
const t: Array<Map<string, number>> = new Array<Map<string, number>>();
t.push(new Map([["test1", 2]]));
t.push(new Map([["test12", 5]]));
Here's an example showing how you can:
create an array of maps
create a new map
set items in the map
push the map into the array
TS Playground
const arrayOfMaps: Array<Map<string, number>> = [];
// create a map
const map1 = new Map<string, number>();
// add entries to the map
map1.set("test1", 1);
map1.set("test2", 2);
// insert the map at the end of the array
arrayOfMaps.push(map1);
console.log(arrayOfMaps); // [Map (2) {"test1" => 1, "test2" => 2}]
const firstMapInArray = arrayOfMaps[0];
console.log(firstMapInArray); // Map (2) {"test1" => 1, "test2" => 2}
console.log(firstMapInArray === map1); // true

Creating a JavaScript function that filters out duplicate in-memory objects?

Okay, so I am trying to create a function that allows you to input an array of Objects and it will return an array that removed any duplicate objects that reference the same object in memory. There can be objects with the same properties, but they must be different in-memory objects. I know that objects are stored by reference in JS and this is what I have so far:
const unique = array => {
let set = new Set();
return array.map((v, index) => {
if(set.has(v.id)) {
return false
} else {
set.add(v.id);
return index;
}
}).filter(e=>e).map(e=>array[e]);
}
Any advice is appreciated, I am trying to make this with a very efficient Big-O. Cheers!
EDIT: So many awesome responses. Right now when I run the script with arbitrary object properties (similar to the answers) and I get an empty array. I am still trying to wrap my head around filtering everything out but on for objects that are referenced in memory. I am not positive how JS handles objects with the same exact key/values. Thanks again!
Simple Set will do the trick
let a = {'a':1}
let b = {'a': 1,'b': 2, }
let c = {'a':1}
let arr = [a,b,c,a,a,b,b,c];
function filterSameMemoryObject(input){
return new Set([...input])
}
console.log(...filterSameMemoryObject(arr))
I don't think you need so much of code as you're just comparing memory references you can use === --> equality and sameness .
let a = {'a':1}
console.log(a === a ) // return true for same reference
console.log( {} === {}) // return false for not same reference
I don't see a good reason to do this map-filter-map combination. You can use only filter right away:
const unique = array => {
const set = new Set();
return array.filter(v => {
if (set.has(v.id)) {
return false
} else {
set.add(v.id);
return true;
}
});
};
Also if your array contains the objects that you want to compare by reference, not by their .id, you don't even need to the filtering yourself. You could just write:
const unique = array => Array.from(new Set(array));
The idea of using a Set is nice, but a Map will work even better as then you can do it all in the constructor callback:
const unique = array => [...new Map(array.map(v => [v.id, v])).values()]
// Demo:
var data = [
{ id: 1, name: "obj1" },
{ id: 3, name: "obj3" },
{ id: 1, name: "obj1" }, // dupe
{ id: 2, name: "obj2" },
{ id: 3, name: "obj3" }, // another dupe
];
console.log(unique(data));
Addendum
You speak of items that reference the same object in memory. Such a thing does not happen when your array is initialised as a plain literal, but if you assign the same object to several array entries, then you get duplicate references, like so:
const obj = { id: 1, name: "" };
const data = [obj, obj];
This is not the same thing as:
const data = [{ id: 1, name: "" }, { id: 1, name: "" }];
In the second version you have two different references in your array.
I have assumed that you want to "catch" such duplicates as well. If you only consider duplicate what is presented in the first version (shared references), then this was asked before.

Is it good practice to use a object literal as a hash table?

Is it good practice to use a object literal as a hash table? i.e use a property name as the key to get a particular mapped value back.
For example:
var colorArray = [
{ code: "#4286f4", name: "Blue" },
{ code: "#fc4d02", name: "Red" }
]
var hashTable = {}
colorArray.forEach(color => {
hashTable[color.code] = color.name
})
Is this an acceptable use for object literals, or is there a pattern out there that will better handle a hash map in JavaScript?
Before ES6 using a literal object was the only way to have a hashmap in JS. Since ES6, you can also use Map:
const colorArray = [{code: "#4286f4" , name: "Blue"}, {code: "#fc4d02", name: "Red"}];
const map = new Map(colorArray.map(({ code, name }) => [code, name]));
console.log(map); // look at the browser's console
console.log(map.get("#4286f4"));

how to push a new item into a deeply nested Record in immutableJS

I'm trying to push a new item into a deeply nested immutable record.
const i = Immutable.Record({
nested: new (Immutable.Record({
someKey: [{id:1,name:'adam'}, {id:2,name:'steve'}],
})),
});
const myMap = new i;
const myNewMap = myMap.updateIn(['nested', 'someKey'], (fav)=> fav.push({id:3,name:'dan'}));
console.log(myNewMap.toJS());
what I expect is to update the nested list with the new value, but the actual output is
[object Object] {
nested: [object Object] {
someKey: 3
}
}
so Im doing something wrong, so how would I go about updating the record with the new value ?
here is the jsbin for the example
http://jsbin.com/nipolimuyu/edit?html,js,console
You're missing return statement in a function you pass to updateIn (note that Array.push does NOT return a resulting array!). It should be:
const myNewMap = myMap.updateIn(
['nested', 'someKey'],
(fav) => {
fav.push({id:3,name:'dan'})
return fav
})
Be careful here.
Your initial obj should all be an immutableJS obj. You can use fromJS().
In your example, you need to add your array as an ImmutableJS list
const i = Immutable.Record({
nested: new (Immutable.Record({
someKey: new Immutable.List([{id:1,name:'adam'}, {id:2,name:'steve'}]),
})),
});
// The bad way, add a normal JS array to an immutableJS Record/map
const i = Immutable.Record({
nested: new (Immutable.Record({
someKey: [{id:1,name:'adam'}, {id:2,name:'steve'}],
})),
});
So at the end you just need to do like you wanted
const myNewMap = myMap.updateIn(['nested', 'someKey'], fav => fav.push({id:3,name:'dan'}));
So now you can use the immutableJS push() function that return a new immutableJS object.

Javascript OOP - multiple instances share same data

I have created a javascript class. When I create instances using the new keyword, I don't know why all of the instances share the same array data.
Can anybody explain why this happens? The Cards array in this example is referenced by all instances I created:
(function (scope) {
//Player class: player information, graphics object
//Contructor: init properties
function Player(opts) {
//INITIALIZE PROPERTIES
this.initialize(opts);
}
Player.prototype = {
AccountID: '',
Position: -1,
UserName: '',
Level: 0,
Avatar: 'av9',
Gold: 0,
Cards: [],
pos: { x: 0, y: 0 },
graphicsObj: {},
assets: {},
Status: 0,
initialize: function (opts) {
//copy all properties to new instance
this.copyProp(opts);
this.setCards();
this.createGraphicObject();
},
//copy properties to instance
copyProp: function (opts) {
for (var prop in opts) {
this[prop] = opts[prop];
}
},
...
...
setCards: function () {
//create new Cards data with default position
this.Cards[0] = new scope.Card({ image: this.assets['cards'] });
this.Cards[1] = new scope.Card({ image: this.assets['cards'] });
this.Cards[2] = new scope.Card({ image: this.assets['cards'] });
}
};
scope.Player = Player;
}(window));
In Javascript functions arrays are not copied. If you reference an array it will always refer to the same array.
If you don't want to pass a reference to the same array, you will have to copy the values over to a new array. This can be simple if the array only contains strings; it can also be complex if the array contains other arrays or objects.
Make a copy of your "cards" array before passing it o your new object:
this.assets['cards'].slice(0); //Makes a copy of your array

Categories