Related
Lets say I receive a parsed json like below:
[{"a":1},{"a":2},{"a":3}]
The keys are the same which is a.
How do I make each a unique so that the map is usable?'
EDIT1:
Results I want:
let myMap = {}; //I declare my variable
//Then I fetch a json and parse it
fetch(link)
.then(function(response) {
return response.json(); //parse the json string
}).then(function(json) {
myMap = json; //set it to myMap to be used
}
For some reason I having duplicate keys although you guys said the json is unique. Do I have to set the json string to myMap first and then only parse it?
Basically you can use an Object as hash table
var data = [{ "a": 1 }, { "a": 2 }, { "a": 3 }],
object = Object.create(null);
data.forEach(function (el) {
object[el.a] = el;
});
console.log(object);
Or a Map
var data = [{ "a": 1 }, { "a": 2 }, { "a": 3 }],
map = new Map;
data.forEach(function (el) {
map.set(el.a, el);
});
console.log(map.get(1));
The advantage of Map over an Object is, the key can be anything. The key is not converted to string. Maps can have an object or other primitive or not primitive values as key.
Also if you have a single value list or want to make sure it IS unique you can use the index supplied like this:
obj.map((item, index) =>
...
)}
Maybe this?
[{a:1},{a:2},{a:3}].map(function(item, index) { item.id = index; return item; });
Map in javascript doesnot need a unique id, it will iterate through all the value. so it will iterate through all the objects irrespective the fact that the key is same
eg:
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
var reformattedArray = kvArray.map(function(obj){
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
Well, [{a:1},{a:2},{a:3}] is already unique... but, It's an Array.
so you cannot access an object {a:2, ...} directly but find index with looping.
If I understand your question right way... you want to make new MAP with unique key a how about this way? - reduce can help us. :)
btw, Nina Scholz's answer is right.
let myMap = {}; //I declare my variable
//Then I fetch a json and parse it
fetch(link)
.then(function(response) {
return response.json(); //parse the json string
}).then(function(json) {
// myMap = json; //set it to myMap to be used
myMap = json.reduce(function(p, n) { p[n.a] = n; return p; }, {});
// n.a or n['a'] - primary key (in sample, [1,2,3...])
// "myMap[1].foo", "myMap[2].bar"
// or change KEY as your taste.
myMap = json.reduce(function(p, n) { p['k' + n.a] = n; return p; }, {});
// "myMap.k1.foo", "myMap.k2.bar"
// It's unique but if you want everything...
myMap = json.reduce(function(p, n) {
var k = 'k' + n.a;
if(p[k] !== undefined) { p[k] = n; }
else if(Array.isArray(p[k])) { p[k].push(n); }
else { p[k] = [p[k]] ; }
return p;
}, {});
}
I have this object:
key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
And I have an array with only types and I need to add the given image to it, the array looks something like this:
[{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}]
Basically I want to loop the array, find the type in the key object and get the given image and save it into the array.
Is there any simple way to do this?
One thing that stands out here for me is the line
...get the given image and save it into the array
I'm assuming this means the original array. I think a better approach would be to map the appropriate keys and values to a new array but I've assumed, for this example, that it's a requirement.
In an attempt to keep the solution as terse as possible and the request for a lodash solution:
_.each(key, function(prop){
_.each(_.filter(types, { type: prop.type }), function(type) { type.image = prop.img });
});
Given the object of keys and an array of objects like so:
var key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var arr = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
We can first create an array of the properties in the object key to make iterating it simpler.
Then loop over the array arr, and upon each member, check with a some loop which image belongs to the member by its type (some returning on the first true and ending the loop).
You can change the forEach to a map (and assign the returned new array to arr or a new variable) if you want the loop to be without side-effects, and not to mutate the original array.
var keyTypes = Object.keys(key);
arr.forEach(function (item) {
keyTypes.some(function (keyType) {
if (key[keyType].type === item.type) {
item.image = key[keyType].img;
return true;
}
return false;
});
});
The smarter thing would be to change the object of the imagetypes so that you could use the type as the accessing property, or create another object for that (as pointed out in another answer).
I'm not sure if this solution is modern, but it does not use any loops or recursion.
object = {
spawn: {type:1, img:app.assets.get('assets/spawn.svg')},
wall: {type:2, img:app.assets.get('assets/wall.svg')},
grass: {type:3, img:app.assets.get('assets/grass.svg')},
spike: {type:4, img:app.assets.get('assets/spike.svg')},
ground: {type:5, img:app.assets.get('assets/ground.svg')}
};
arr = [
{type:1, image:null},
{type:3, image:null},
{type:2, image:null},
{type:2, image:null},
{type:5, image:null}
];
var typeImages = {};
Object.getOwnPropertyNames(object).forEach(function(value){
typeImages[object[value].type] = object[value].img;
});
arr = arr.map(function(value){
return {
type: value.type,
image: typeImages[value.type]
};
});
var key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var typesArray = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
for(var i = 0, j = typesArray.length; i < j; i++)
{
typesArray[i].image = getKeyObjectFromType(typesArray[i].type).img;
}
function getKeyObjectFromType(type)
{
for(var k in key)
{
if(key[k].type == type)
{
return key[k];
}
}
return {};
}
for (var i = 0; i < typesArray.length; i++) {
for (prop in key) {
if (key[prop].type === typesArray[i].type) {
typesArray[i].image = key[prop].img;
}
}
}
It loops through the array ("typesArray"), and for each array item, it go through all the objects in key looking for the one with the same "type". When it finds it, it takes that key object's "img" and saves into the array.
Using lodash (https://lodash.com/):
var key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var initialList = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
var updatedList = _.transform(initialList, function(result, item) {
item.image = _.find(key, _.matchesProperty('type', item.type)).img;
result.push(item);
});
This will go over every item in the initialList, find the object that matched their type property in key and put it in the image property.
The end result will be in updatedList
Not sure if the title of the question is doing it justice, but here is an example. I have object:
var plumber = {
name: 'Mario',
age: 42,
game: 'Super Mario'
}
I am looking for an elegant way of using either jQuery or Undescore to get key and value from this object.
// foo() would be desired elegant function
plumber.foo('name')
#> { name: 'Mario' }
// or even better
plumber.foo(['name','age'])
#> { name: 'Mario', age: 16 }
Thank you!
Underscore.js has _.pick that does exactly that:
var new_obj = _.pick(obj, ['name', 'age']);
I think you could approach this two ways (without either of those two libraries). You can either pass the function an array of keys or you could pass it a variable number of arguments.
fiddle
Using an array
var plumber = {
name: 'Mario',
age: 42,
game: 'Super Mario'
}
var splitObject = function (obj, keys) {
var holder = {};
keys.forEach(function (d) {
holder[d] = obj[d];
})
return holder;
}
var example = splitObject(plumber, ["name", "age"]);
console.log("example #1", example);
Using a variable number of arguments
var variableArguments = function (obj) {
var keys = Array.prototype.slice.apply(arguments).slice(1),
holder = {};
keys.forEach(function (d){
holder[d] = obj[d];
})
return holder;
}
var example2 = variableArguments(plumber, "name", "age");
console.log("example #2", example2);
Underscore.js probably has its own function for this. You'd have to check the documentation.
edit:
pick is probably the most appropriate function, as per the comments above.
Not sure what exactly you're trying to accomplish here, as your first example could be accomplished easily by calling:
plumber.name;
if you were unsure of what the input would be, and needed to pass a variable, you can do it like this:
var arg = 'name';
plumber[arg];
Your second example is a little more complex, for these purposes I'm going to assume you want to be able to pass an arbitrary array of keys and return an object containing the key/value pairs for each one. If you are comfortable with prototyping global objects, you could do this:
Object.prototype.getValuesFromKeys = function (keys) {
var ret = {};
for (var i = 0; i < arr.length; i++) {
ret[keys[i]] = this[keys[i]];
}
return ret;
};
plumber.getValuesFromKeys(['name','age']);
If you want that functionality without prototyping the global Object, you could build it this way instead:
function getValuesFromKeys(obj, keys) {
var ret = {};
for (var i = 0; i < arr.length; i++) {
ret[keys[i]] = obj[keys[i]];
}
return ret;
};
getValuesFromKeys(plumber, ['name','age']);
I have an array into which I insert a load of values along with their corresponding keys. They are inserted fine as I can see them all in the array when I do a console.log.
The issue is, I can't seem to retrieve the values from the array using their respective keys.
Here is my code.
var personArray = [];
personArray.push({
key: person.id,
value:person
});
var personID = person.id;
console.log(personArray.personID);
I have also tried console.log(personArray[personID]; but this does not work either.
The value I get in my console is undefined.
What you are doing is that you push dictionaries into the array. If person.id is unique, then you can do this:
var personDict = {}
personDict[person.id] = person
and then personDict[personID] will work. If you want to keep your structure, then you have to search inside the array for it:
var personArray = [];
personArray.push({
key: person.id,
value:person
});
var personID = person.id;
var search = function(id) {
var l = personArray.length;
for (var i = 0; i < l; i++) {
var p = personArray[i];
if (p.key === id) {
return p.value;
}
}
return null;
};
search(personID);
You can use dictionary format as suggested by #freakish,
Or use the filter function to find the required object.
For example:
var personArray = [];
var person = {id: 'aki', value:'Akhil'}
personArray.push({
key: person.id,
value:person
});
personArray.filter(function(item){
return item.key == 'aki'
});
I have a variable which is an array and I want every element of the array to act as an object by default. To achieve this, I can do something like this in my code.
var sample = new Array();
sample[0] = new Object();
sample[1] = new Object();
This works fine, but I don't want to mention any index number. I want all elements of my array to be an object. How do I declare or initialize it?
var sample = new Array();
sample[] = new Object();
I tried the above code but it doesn't work. How do I initialize an array of objects without using an index number?
Use array.push() to add an item to the end of the array.
var sample = new Array();
sample.push(new Object());
To do this n times use a for loop.
var n = 100;
var sample = new Array();
for (var i = 0; i < n; i++)
sample.push(new Object());
Note that you can also substitute new Array() with [] and new Object() with {} so it becomes:
var n = 100;
var sample = [];
for (var i = 0; i < n; i++)
sample.push({});
Depending on what you mean by declaring, you can try using object literals in an array literal:
var sample = [{}, {}, {} /*, ... */];
EDIT: If your goal is an array whose undefined items are empty object literals by default, you can write a small utility function:
function getDefaultObjectAt(array, index)
{
return array[index] = array[index] || {};
}
Then use it like this:
var sample = [];
var obj = getDefaultObjectAt(sample, 0); // {} returned and stored at index 0.
Or even:
getDefaultObjectAt(sample, 1).prop = "val"; // { prop: "val" } stored at index 1.
Of course, direct assignment to the return value of getDefaultObjectAt() will not work, so you cannot write:
getDefaultObjectAt(sample, 2) = { prop: "val" };
You can use fill().
let arr = new Array(5).fill('lol');
let arr2 = new Array(5).fill({ test: 'a' });
// or if you want different objects
let arr3 = new Array(5).fill().map((_, i) => ({ id: i }));
Will create an array of 5 items. Then you can use forEach for example.
arr.forEach(str => console.log(str));
Note that when doing new Array(5) it's just an object with length 5 and the array is empty. When you use fill() you fill each individual spot with whatever you want.
After seeing how you responded in the comments. It seems like it would be best to use push as others have suggested. This way you don't need to know the indices, but you can still add to the array.
var arr = [];
function funcInJsFile() {
// Do Stuff
var obj = {x: 54, y: 10};
arr.push(obj);
}
In this case, every time you use that function, it will push a new object into the array.
You don't really need to create blank Objects ever. You can't do anything with them. Just add your working objects to the sample as needed. Use push as Daniel Imms suggested, and use literals as Frédéric Hamidi suggested. You seem to want to program Javascript like C.
var samples = []; /* If you have no data to put in yet. */
/* Later, probably in a callback method with computed data */
/* replacing the constants. */
samples.push(new Sample(1, 2, 3)); /* Assuming Sample is an object. */
/* or */
samples.push({id: 23, chemical: "NO2", ppm: 1.4}); /* Object literal. */
I believe using new Array(10) creates an array with 10 undefined elements.
You can instantiate an array of "object type" in one line like this (just replace new Object() with your object):
var elements = 1000;
var MyArray = Array.apply(null, Array(elements)).map(function () { return new Object(); });
Well array.length should do the trick or not? something like, i mean you don't need to know the index range if you just read it..
var arrayContainingObjects = [];
for (var i = 0; i < arrayContainingYourItems.length; i++){
arrayContainingObjects.push {(property: arrayContainingYourItems[i])};
}
Maybe i didn't understand your Question correctly, but you should be able to get the length of your Array this way and transforming them into objects. Daniel kind of gave the same answer to be honest. You could just save your array-length in to his variable and it would be done.
IF and this should not happen in my opinion you can't get your Array-length. As you said w/o getting the index number you could do it like this:
var arrayContainingObjects = [];
for (;;){
try{
arrayContainingObjects.push {(property: arrayContainingYourItems[i])};
}
}
catch(err){
break;
}
It is the not-nice version of the one above but the loop would execute until you "run" out of the index range.
//making array of book object
var books = [];
var new_book = {id: "book1", name: "twilight", category: "Movies", price: 10};
books.push(new_book);
new_book = {id: "book2", name: "The_call", category: "Movies", price: 17};
books.push(new_book);
console.log(books[0].id);
console.log(books[0].name);
console.log(books[0].category);
console.log(books[0].price);
// also we have array of albums
var albums = []
var new_album = {id: "album1", name: "Ahla w Ahla", category: "Music", price: 15};
albums.push(new_album);
new_album = {id: "album2", name: "El-leila", category: "Music", price: 29};
albums.push(new_album);
//Now, content [0] contains all books & content[1] contains all albums
var content = [];
content.push(books);
content.push(albums);
var my_books = content[0];
var my_albums = content[1];
console.log(my_books[0].name);
console.log(my_books[1].name);
console.log(my_albums[0].name);
console.log(my_albums[1].name);
This Example Works with me.
Snapshot for the Output on Browser Console
Try this-
var arr = [];
arr.push({});
const sample = [];
list.forEach(element => {
const item = {} as { name: string, description: string };
item.name= element.name;
item.description= element.description;
sample.push(item);
});
return sample;
Anyone try this.. and suggest something.
Use array.push() to add an item to the end of the array.
var sample = new Array();
sample.push(new Object());
you can use it
var x = 100;
var sample = [];
for(let i=0; i<x ;i++){
sample.push({})
OR
sample.push(new Object())
}
Using forEach we can store data in case we have already data we want to do some business login on data.
var sample = new Array();
var x = 10;
var sample = [1,2,3,4,5,6,7,8,9];
var data = [];
sample.forEach(function(item){
data.push(item);
})
document.write(data);
Example by using simple for loop
var data = [];
for(var i = 0 ; i < 10 ; i++){
data.push(i);
}
document.write(data);
If you want all elements inside an array to be objects, you can use of JavaScript Proxy to apply a validation on objects before you insert them in an array. It's quite simple,
const arr = new Proxy(new Array(), {
set(target, key, value) {
if ((value !== null && typeof value === 'object') || key === 'length') {
return Reflect.set(...arguments);
} else {
throw new Error('Only objects are allowed');
}
}
});
Now if you try to do something like this:
arr[0] = 'Hello World'; // Error
It will throw an error. However if you insert an object, it will be allowed:
arr[0] = {}; // Allowed
For more details on Proxies please refer to this link:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
If you are looking for a polyfill implementation you can checkout this link:
https://github.com/GoogleChrome/proxy-polyfill
The below code from my project maybe it good for you
reCalculateDetailSummary(updateMode: boolean) {
var summaryList: any = [];
var list: any;
if (updateMode) { list = this.state.pageParams.data.chargeDefinitionList }
else {
list = this.state.chargeDefinitionList;
}
list.forEach((item: any) => {
if (summaryList == null || summaryList.length == 0) {
var obj = {
chargeClassification: item.classfication,
totalChargeAmount: item.chargeAmount
};
summaryList.push(obj);
} else {
if (summaryList.find((x: any) => x.chargeClassification == item.classfication)) {
summaryList.find((x: any) => x.chargeClassification == item.classfication)
.totalChargeAmount += item.chargeAmount;
}
}
});
if (summaryList != null && summaryList.length != 0) {
summaryList.push({
chargeClassification: 'Total',
totalChargeAmount: summaryList.reduce((a: any, b: any) => a + b).totalChargeAmount
})
}
this.setState({ detailSummaryList: summaryList });
}
var ArrayofObjects = [{}]; //An empty array of objects.