Object Keys to Array - javascript

The challenge asks us to create an array from a given object's keys (without using Objects.keys).
Here is my code:
function getAllKeys(object){
var array = [];
for(var key in object){
array.push(key);
return array;
}
}
var myObj={
name:"bellamy",
age:25 };
getAllKeys(myObj);
For some reason it's only returning the first key
[ 'name' ]
Any help would be much appreciated! I'm sure it's a simple fix, just one I'm not aware of as an extreme novice.

You need to move your return outside of your loop:
function getAllKeys(object){
var array = [];
for(var key in object){
array.push(key);
}
return array;
}
var myObj = {
name:"bellamy",
age:25
};
getAllKeys(myObj);
This is because your function will immediately return when it first encounters return, which in your example is in the first iteration of the loop.

Related

javascript: adding strings into an object through a class method

I'm trying to create a javascript class with a couple of methods that would let me add view and delete. I'm stuck with the add method, it should return me a unique ID of each string passed into the add method, but instead I can't figure out how to jump to a next code block when I'm done adding strings. Below is some of my current code:
var obj = {};
var arr = [];
var Words = function(){
this.add = function(newWord){
if(newWord !== false){
arr.push(newWord);
} else {
for (var i = 0; i < arr.length; i++){
obj[i] = arr[i];
return obj[i];
}
}
var words = new Words();
words.add('first');
words.add('second');
words.add('third');
I feel I should be creating a next() function of some sort that runs after I'm done pushing the last passed string, but I seem to have forgotten everything.
While I don't really know what you're trying to accomplish, there are some problems with your code...
An Object has keys and values. For every key there is a value.
Ex. mykey: "corresponding value"
for (var i = 0; i < arr.length; i++){
obj[i] = arr[i];
return obj[i];
}
You are setting obj[i] when i is an integer, so unless your keys are integers (probably not), you need to specify keys.
Otherwise, use another array for what you are doing (if possible).
If you are actually filling this object with keys that are numerals, then ignore the above.
I would also point you to using callbacks for finding out when .add() is finished (or just run your code after running .add() ??).
Why not just create an array, set it's values as you want, and retrieve them based on iteration?
var array = [];
//add
array.push("first");
//view value
console.log(array[0]); // output: "first"
//view index
array.indexOf("first"); // output 0
//delete
array.splice(0, 1);
Then wrap this as a class if you'd like:
var array = [];
var Words = function() {
this.add = function(input) {
array.push(input);
}
this.view = function(input) {
return array[input];
}
this.delete = function(input) {
array.splice(input, 1);
}
}
Hope this helps.

How do you push a specified number of objects to an array?

I'm pretty new to javascript but I'm trying to push a specified number of objects to an array using the following code. When I check the console I see only one object is pushed to the array. What should I be doing differently? Thanks!
var albums = {};
function collection(numberOfAlbums) {
array = [];
array.push(albums);
return array;
};
console.log(collection(12));
From your code:
array.push(albums);
would add the same object each time (assuming you had added a loop) which isn't what you want.
This will add a new empty object for each iteration of numberOfAlbums:
function collection(numberOfAlbums) {
for (var array = [], i = 0; i < numberOfAlbums; i++) {
array.push({});
}
return array;
};
Here's another way using map. Array.apply trick from here.
function collection(numberOfAlbums) {
var arr = Array.apply(null, Array(numberOfAlbums));
return arr.map(function (el) { return {}; });
};
I could give you the code but that is not learning. So here are the steps:
use numberOfAlbums as an argument in a function.
create an empty array.
use numberOfAlbums in for-loops in that for-loops push albums. ==array.push(albums)== do not use {}curly brackets around albums.
return the array.

How do you search object for a property within property?

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

Javascript/jQuery: nesting loops, prevent overwriting object property

I have a function which should built an array with keys. Those keys will have a serie of objects as value.
I've some loops nested in each other and I'm quite near to the solution, but inside the last loop I'm making a mistake and I can't see the solution.
The function loopt over an array with Id's. Those will be the key value for the output array. After that it loops over an array with a lot of objects. Those objects are having a property 'category'. Some of them have one, others more. So with a for-loop I loop over all the categories.
If the categorie is the same as the id then it should push the object to the var objs, which will be added to the right key.
This is all working, BUT, I want that the objects are saved with only ONE category. So I declared a new var inside the last loop, put the obj inside there and set the obj.category. Unfortunately this is overwriting the 'source', array[x].category. This is not good because this occurs the problem that an object with two categories will only be found once in this function and it had to be found twice so it can be saved twice (once by every represent key value).
A lot of explanation for a little piece of code...
$.each(unique_id, function(i, el){
var objs = [];
for(var x in array)
{
for(var j=0; j<array[x].category.length; j++)
{
if(array[x].category[j] == el)
{
var obj = array[x];
obj.category = el;
objs.push(obj);
}
}
}
data[el] = objs;
})
What is happening is : both obj and array[x] are pointing to same object. they are two references that point to same object .Can you try below:
$.each(unique_id, function(i, el){
var objs = [];
for(var x in array)
{
for(var j=0; j<array[x].category.length; j++)
{
if(array[x].category[j] == el)
{
var obj = {};
$.extend(true,obj,array[x]);
obj.category = el;
objs.push(obj);
}
}
}
data[el] = objs;
});
Also, in javascript variables are function-scoped so even if you declare them inside the inner loop they are visible throughout the function and not only in the inner loop in which you have defined it. Of course $extend will copy every property that exists on array[x] and the nested objects and their properties as well. if you don't want that. just use
var obj = {};
obj.category = array[x].category;
provided category is also not object.

How to sort a JS object of objects?

I have built an object in PHP, used JSON_encode function and send it as a JSON string to my JS script via ajax. Then I convert it back to an object. The problem I am having is that I wanted to keep the object in the order that it was originally created in. Please see this picture of what the object looks like once I get it into JS:
When I created the object, it was sorted by the customer field alphabetically. The customer name starting with A would come first, B second, etc. As you can see, now, the first element of the object as customer starting with S. It looks like somehow it got automatically sorted by the key of the top-level object, which is an integer, so I understand why this happened.
So i want to do is re-sort this object so that all the sub-objects are sorted by the customer field alphabetically. Is this possible? If so, how do I do it?
Thanks!
I've changed Fabricio Matée answer to become more flexible and return the sorted object.
function alphabetical_sort_object_of_objects(data, attr) {
var arr = [];
for (var prop in data) {
if (data.hasOwnProperty(prop)) {
var obj = {};
obj[prop] = data[prop];
obj.tempSortName = data[prop][attr].toLowerCase();
arr.push(obj);
}
}
arr.sort(function(a, b) {
var at = a.tempSortName,
bt = b.tempSortName;
return at > bt ? 1 : ( at < bt ? -1 : 0 );
});
var result = [];
for (var i=0, l=arr.length; i<l; i++) {
var obj = arr[i];
delete obj.tempSortName;
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var id = prop;
}
}
var item = obj[id];
result.push(item);
}
return result;
}
Then just call the function like this
your_object = alphabetical_sort_object_of_objects(your_object, 'attribute_to_sort');
It's probably the difference between a JavaScript Object and a JavaScript Array. Objects are more like hash tables, where the keys aren't sorted in any particular order, whereas Arrays are linear collections of values.
In your back end, make sure you're encoding an array, rather than an object. Check the final encoded JSON, and if your collection of objects is surrounded by {} instead of [], it's being encoded as an object instead of an array.
You may run into a problem since it looks like you're trying to access the objects by an ID number, and that's the index you want those objects to occupy in the final array, which presents another problem, because you probably don't want an array with 40,000 entries when you're only storing a small amount of values.
If you just want to iterate through the objects, you should make sure you're encoding an array instead of an object. If you want to access the objects by specific ID, you'll probably have to sort the objects client-side (i.e. have the object from the JSON response, and then create another array and sort those objects into it, so you can have the sorted objects and still be able to access them by id).
You can find efficient sorting algorithms (or use the one below from ELCas) easily via Google.
Here's a generic iteration function which pushes all objects into an array and sorts them by their customer property in a case-insensitive manner, then iterates over the sorted array:
function iterate(data) {
var arr = [];
for (var prop in data) {
if (data.hasOwnProperty(prop)) {
var obj = {};
obj[prop] = data[prop];
obj.tempSortName = data[prop].customer.toLowerCase();
arr.push(obj);
}
}
arr.sort(function(a, b) {
var at = a.tempSortName,
bt = b.tempSortName;
return at > bt ? 1 : ( at < bt ? -1 : 0 );
});
for (var i = 0, l = arr.length; i < l; i++) {
var obj = arr[i];
delete obj.tempSortName;
console.log(obj);
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var id = prop; //gets the obj "index" (id?)
}
}
console.log(id);
var item = obj[id];
console.log(item.customer);
//do stuff with item
}
}
Fiddle
sortObject(object){
if(typeof object === 'object'){
if(object instanceof Date){
return object;
}
if(object instanceof Array){
return object.map(element => this.sortObject(element));
} else {
return Object.keys(object).sort().reduce((result, key) => {
if(object[key] && object[key] !== null) {
result[key] = this.sortObject(object[key]);
}
return result;
}, {});
}
}
return object;
}

Categories

Resources