How to replace the javascript object property name dynamically - javascript

I have created a JavaScript object like
var obj={}
var prop = {}
prop.name= "name",
prop.value = "10"
obj[old_name] = prop;
I need to change the old_name to new_name. I have tried
obj[new_name] = obj[old_name];
delete obj[old_name];
And it works but, the object order gets changed.
For example:
{"obj1":{"name:name","value:10"},"obj2":{"name:name","value:10"}}
If I replace obj1 with objone, like this:
obj[objone ] = obj[obj1];
delete obj[obj1 ];
The object order changed to:
{"obj2":{"name:name","value:10"},"objone":{"name:name","value:10"}}]
But I need to change the property name alone and not the order, and I also try string replace but I think it is not the proper way, so please suggest me some ideas.

Objects have no order. Any apparent order you see is unspecified behavior and you cannot rely on it. They didn't when the question was asked, but they do now:
Let keys be a new empty List.
For each own property key P of O that is an integer index, in ascending numeric index order
Add P as the last element of keys.
For each own property key P of O that is a String but is not an integer index, in property creation order
Add P as the last element of keys.
For each own property key P of O that is a Symbol, in property creation order
Add P as the last element of keys.
Return keys.
Your way of renaming the property is the only way of doing it: Creating a new one, then removing the old one. Doing that will change where it appears in the order of the object, because it was created after the previous property.
If you need order, use an array. While theoretically arrays don't have order either (because they're not really arrays), we have the convention that they have order, based on then numeric value of the indexes of the entries: The entry at index 0 is before the entry at index 1 and so on. (And modern JavaScript engines can and do use real arrays where possible.)

Related

In javascript how to replace elements of an array to it's corresponding values in another object?

I have the mapping of abbreviation and full name as follow:
object = {"TSLA":"TESLA INC.","GOOG":"GOOGLE INC.","APPL":"APPLE INC.","AMZN":"AMAZON CORPORATION", "MSFT":"MICROSOFT CORPORATION"}
as an output of function i get the following array:
array = ["AMZN","APPL"]
I want to display the values of the associated keys as follows:
output_array = ["AMAZON CORPORATION", "APPLE INC."]
Note that, the actual object has more key: value pairs
Using IndexOf() I can replace one value. However, I believe there must be a way of mapping the array elements to replace the values at once.
Since I am new to JS, I would appreciate any suggestion.
array.map(abbr => object[abbr]) does the job; it iterates over the array rather than the object, which is more efficient as the object already is a lookup table with the right keys - you are right, there is no need to use indexOf which uses a linear search.

Passing associative array as props not working

I have a React application which handles rooms and their statistics.
Previously, I had the code set up to pass as props to the next component:
the raw statistics (not a concern for the question)
an array of all the rooms set up as follows
I figured it would be simpler for me, though, to have the list of all rooms as an associative array where the keys of each element is the same as the ID it contains. To do that, I utilized a code similar to this in a for loop:
roomsList[rooms[v].ID] = rooms[v];
So that the result would be:
[a001: {...}, a002: {...}, ...]
I then proceeded to pass this style of array, and not the standard one with a numeric index, as a prop to the next component as such:
<StatsBreakdown stats={computedStats.current} roomsList={roomsList} />
BUT
Now, the next component sees that prop as an empty array.
Even more weirdly, if I initialize that roomsList array with a random value [0] and then do the same process, I end up with:
I cannot cycle through the array with .map, and, according to JS, the length is actually 0, it's not only Google Chrome.
Is there something I'm missing about the way JSX, JS or React work?
Your original roomsList was an array of objects, whose indices were 0,1,2 etc. roomsList[rooms[v].ID] = rooms[v]; implies you are inserting elements not using a number but an alphanumeric string. Hence your resulting array is no longer an array but an object.
So we can cycle over the object using Object.keys().
const renderRoomDets = Object.keys(roomsList).map(room => {
roomOwner = roomsList[room].owner_id;
return (
<div>
<p>{`Room Owner ${roomOwner}`}</p>
</div>
);
});
But I believe your original form is ideal, because you are reaping no special benefits from this notation.
A better alternative maybe using .find() or .findIndex() if you want iterate over an array based on a specific property.
const matchedRoom = roomsList.find(room => room.ID === 'Srf4323')
Iterate the new array using its keys not indexes.
Or even better store your data in an actual object instead of an array since you're using strings for ids.
First define your object like so:
let data = {};
Then start adding records to it. I'd suggest deleting the ID attribute of the object since you're storing it in the key of your record, it's redundant, and it won't go anywhere unless u delete the entry.
data[ID] = row;
To delete the ID attribute (optional):
row.ID = null;
delete row.ID;
Then iterate through it using
for(let key in data){}

How do you iterate over a JavaScript object's properties like an array?

I don't mean using a for loop using the keys.
For example if you had an array like:
var fruitArray = ["Apples", "Bananas", "Coconuts"],
curFruit = 0;
You could "iterate" over that using buttons, say you've got a prev/next button and all those buttons do is decrement/increment the curFruit index.
So if I'm on Bananas, I could get Apples using the prev button using:
fruitArray[0] // Apples
Where the index was at 1 for Bananas but the prev button drops the index by one.
So with an unknown-length object, and not using a numbered-index, how could you do that?
Say it's like this:
var fruitObject = {"Apples":"Red", "Bananas":"Yellow", "Coconuts":"Brown"};
I realize you could have set 0, 1, 2 and the fruit name, but just to show that you don't know what the object key/index might be.
So if I'm on Bananas using
fruitObject.Bananas // yellow
How could I get to Apples using the same decrement idea as the Array?
My question is not about the for in method
I don't know why that's not clear, it was literally the first line in my question.
I think I found a solution anyway though it might not be direct/the most effective way to do it where I'll create a temporary local "look up".
To explain:
Here's an object
var colorObject = {"red":"apple", "blue":"blueberries", "yellow":"banana"};
I don't want to use the for in method to go from left to right complete.
I want to be able to start/keep a current position like I'm at "blue":"berries" and I can jump to "red":"apple" without knowing what "red":"apple" is
My current solution in mind is, yes, though ironically I would use the for in method but to create a look up array.
Something like
var tempArray = [];
for (var key in colorObject) {
tempArray.push(key);
}
Then I can navigate the object starting from anywhere using the increment/decrement method.
tempArray[1] would return "blue" and I could go to "red" by doing tempArray[0] which is interpreted as
colorObject.blue // blueberries
Edit thanks to the editor for making my question more clear
I did poorly word it so that's on me.
This is not possible. JavaScript object properties do not have a defined order, so there is no concept of Y key comes after X key.
Excerpt from EnumerateObjectProperties section of ECMAScript 2017 Draft (ECMA-262) (emphasis added):
The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.
If you were to iterate over the properties of your fruitObject object, "Bananas" may or may not come before "Coconuts", this behavior simply is not defined by the specification. There does not even appear to be a guarantee the properties will come back in the same order each time you iterate over the properties.
The only way to have a consistent order would be to have an array. Optionally, you could do this by creating an array of the properties via Object.keys.
var fruitObject = {"Apples":"Red", "Bananas":"Yellow", "Coconuts":"Brown"};
// Get the property keys in an ordered list:
var fruitObjectKeys = Object.keys(fruitObject);
// An array of properties with a consistent order:
fruitObjectKeys.forEach(function(prop) {
console.log(prop, '=', fruitObject[prop]);
});
Note however that the JavaScript engine running the code will decide what the order of the resulting array of properties is if you do it this way.
Objects don't have order, so you can't say that the first element of fruitObject is "Apples", the second is "Bananas" and the third is "Cocounts".
You could get the keys as an array with Object.keys() and then do something like
var keys=Object.keys(fruitObject);
fruitObject[keys[0]];
Remember that in JS it's the obj.key is the same than obj["key"].

Why can't you access this array with index?

Why does this array have a length property of 0? And as a follow up to that question, why can't you access an item in this array with an index value?
Consider the following:
var box = [];
box['material'] = 'cardboard';
box['size'] = 'small';
box.length; //0
console.log(box);
//[ material: 'cardboard', size: 'small' ]
box[0]; //undefined
However, when I do the following:
var box = [];
box['0'] = true;
box['1'] = 'cardboard';
box['2'] = 'some value';
box.length; //3
box[0];// true
Why does it output the correct length in this case, since '0' is a string and not a number and access the correct item with the 0 index?
In JavaScript, the length of an array is always one more than the largest numeric (integer) property name. Arrays can have properties whose names are not numeric, but they don't count towards the length of the array (and they are ignored in some other important situations).
Object property names are always strings, but strings that are non-negative integer values when interpreted as numbers are special in arrays. Accessing properties with numeric values works because the numbers are first converted to strings; thus box[0] and box['0'] do exactly the same thing.
when setting box['material'] it creates a property called 'material' with value 'cardboard'. this doesn't add a element to the list!
you need to use .push() or asign the index you want.
also, the '0' string is cased to a number, so obj['0'] and obj[0] is the same (not just for 0, this happens for all numbers)
I think you’re confusing objects with arrays. While arrays are indeed objects in javascript, that doesn’t help us here.
What you are trying to instantiate is an associative array with key-value pairs “material”->“cardboard”, “size”->“small”. However, such a datastructure does not exist in javascript. Array must only have integers as indexes, as in
box = [];
box[0] = 'material';
box[1] = 'someValue';
The reason why your code (which only seems to be an associative array)
box = [];
box['0'] = true;
box['1'] = 'cardboard';
works is because of implicit type conversion. Because you’ve declared box to be an array, a string is not valid in this position, so javascript quietly converts it into an integer, so you again get a plain, boring, integer-indexed array as above.
What you can do, though, is create an object with attributes. So you might, for example, state
box = {}; // box is now an object
box.size = 'small'; // box now has an attribute called “size”
// which has the (string) value “'small'”
box.material = 'cardboard';
or at one go using the notation for object literals:
box = {
size: 'small',
material: 'cardboard'
};
This is the closest you can get to associative arrays in javascript. Note that objects do not have a length. If you want to access the number of attributes they have, you have to use Object.keys(box).length. To iterate over the keys, use
for(var key in box){
console.log('value of ' + key + ' is ' + box[key])
}
Note the array-like notation here, but remember: You’re dealing with objects, not arrays, though dealing with them looks similar. Since box is of type object, you will not only get the attributes you have defined yourself, but also any attributes which are defined for every object. To get only the keys you put in there yourself, use
for (var key in box) {
if (box.hasOwnProperty(key)) {
// do stuff
}
}
If you need to add keys, i.e. attributes at runtime, use (for example)
//supposing that box was instantiated as above
var listOfBoxAttributes = ['shape', 'color', 'weight'];
for(var i in listOfBoxAttributes)
box[listOfBoxAttributes[i]] = undefined;

best way to append an item to a list within a JSON object?

I'm working on JavaScript and I have this JSON object:
var obj ={"name" : "objName",
"dynamicList" :[]};
and then I add some items to my list like this:
obj.dynamicList["someStringID"] = {"watever"};
It's important that I use a string as indexer for each item on my list (i didn't know this could be done until recently).
My only problem now is that whenever I ask for obj.dynamicList.lenght I get 0, unles I manually set the proper number... I was wondering if there's a better way to add items to my list?
Thanks!!
In Javascript, string index is not really an index. It's actually an attribute of the array object. You could set and get the value with the string index, but it's actually an empty array with some attributes. Not only .length, but also .sort(), .splice(), and other array function would not work. If there is a need to use array functions, I would use number as an index to make it a real item in the array.
If you have to use the string as an index, you couldn't rely on .length function. If there is no need to support IE prior to version 9, the Object.keys as suggested by #strimp099 should work. or you may have to create function to count the number of attributes for example:
function len(obj) {
var attrCount = 0;
for(var k in obj) {
attrCount++;
}
return attrCount;
}
and then call
len(obj.dynamicList);
Use the following the find the length of dynamicList object:
Object.keys(obj.dynamicList).length
To do this "the right way," you will have to make obj.dynamicList an object instead of an array; use {} instead of [] to set the initial value.
How to efficiently count the number of keys/properties of an object in JavaScript?
dynamiclist is an object, the length is not the length property you expect from an array.

Categories

Resources