How should I replace the key strings in a Javascript key:value hash map (as an object)?
This is what I have so far:
var hashmap = {"aaa":"foo", "bbb":"bar"};
console.log("before:");
console.log(hashmap);
Object.keys(hashmap).forEach(function(key){
key = key + "xxx";
console.log("changing:");
console.log(key);
});
console.log("after:");
console.log(hashmap);
See it running in this jsbin.
The "before" and "after" hashmaps are the same, so the forEach seems to be in a different scope. How can I fix it? Perhaps there are better ways of doing this?
It has nothing to do with scope. key is just a local variable, it's not an alias for the actual object key, so assigning it doesn't change the object.
Object.keys(hashmap).forEach(function(key) {
var newkey = key + "xxx";
hashmap[newkey] = hashmap[key];
delete hashmap[key];
});
if keys order is important you can use:
const clone = Object.fromEntries(
Object.entries(o).map(([o_key, o_val]) => {
if (o_key === key) return [newKey, o_val];
return [o_key, o_val];
})
);
this will create an object with the new key in the same place where the old one was.
You are just changing the copy of the object's keys, so the original object won't be changed. You can create an new object to hold the new keys, like this:
var hashmap = {"aaa":"foo", "bbb":"bar"};
console.log("before:");
console.log(hashmap);
var newHashmap = {};
Object.keys(hashmap).forEach(function(key){
var value = hashmap[key];
key = key + "xxx";
console.log("changing:");
console.log(key);
newHashmap[key] = value;
});
console.log("after:");
console.log(newHashmap);
You can use Array.prototype.reduce().
const hashmap = { aaa: 'foo', bbb: 'bar' };
const newHashmap = Object.entries(hashmap).reduce((acc, [key, value]) => ({
...acc,
[`${key}xxx`]: value,
}), {});
console.log(newHashmap);
// { aaaxxx: 'foo', bbbxxx: 'bar' }
The function takes as an argument the original map and returns a new one with the keys altered. The call of the mapT(m) just returns the transformed map with the new keys.
function mapT(map){
const x = new Map();
for (const [k, v] of map) {
x.set(k+ "xxx", v);
}
return x;
}
Simple call : var new_map = mapT(mapA);
Related
I am building some objects in JavaScript and pushing those objects into an array, I am storing the key I want to use in a variable then creating my objects like so:
var key = "happyCount";
myArray.push( { key : someValueArray } );
but when I try to examine my array of objects for every object the key is "key" instead of the value of the variable key. Is there any way to set the value of the key from a variable?
Fiddle for better explanation:
http://jsfiddle.net/Fr6eY/3/
You need to make the object first, then use [] to set it.
var key = "happyCount";
var obj = {};
obj[key] = someValueArray;
myArray.push(obj);
UPDATE 2021:
Computed property names feature was introduced in ECMAScript 2015 (ES6) that allows you to dynamically compute the names of the object properties in JavaScript object literal notation.
const yourKeyVariable = "happyCount";
const someValueArray= [...];
const obj = {
[yourKeyVariable]: someValueArray,
}
In ES6, you can do like this.
var key = "name";
var person = {[key]:"John"}; // same as var person = {"name" : "John"}
console.log(person); // should print Object { name="John"}
var key = "name";
var person = {[key]:"John"};
console.log(person); // should print Object { name="John"}
Its called Computed Property Names, its implemented using bracket notation( square brackets) []
Example: { [variableName] : someValue }
Starting with ECMAScript 2015, the object initializer syntax also
supports computed property names. That allows you to put an expression
in brackets [], that will be computed and used as the property name.
For ES5, try something like this
var yourObject = {};
yourObject[yourKey] = "yourValue";
console.log(yourObject );
example:
var person = {};
var key = "name";
person[key] /* this is same as person.name */ = "John";
console.log(person); // should print Object { name="John"}
var person = {};
var key = "name";
person[key] /* this is same as person.name */ = "John";
console.log(person); // should print Object { name="John"}
var key = "happyCount";
myArray.push( { [key] : someValueArray } );
Use this.
var key = 'a'
var val = 'b'
console.log({[key]:val})
//a:'b'
In ES6 We can write objects like this
const key= "Name";
const values = "RJK"
const obj = {
[key]: values,
}
In TypeScript, it should look something like this
let title ="Current User";
type User = {
[key:string | number | symbol]: any
};
let myVar: User = {};
myVar[ title ] = "App Developer";
console.log(myVar)// Prints: { Current User:"App Developer"}
let key = "name";
let name= "john";
const obj ={
id:01
}
obj[key] = name;
console.log(obj); // output will {id:01,name:"john}
Use square brackets shown it will set as key
The Reality
The problem in JS is simply that:
{ x: 2 }
is THE SAME as:
{ "x": 2 }
(even if you have x a variable defined!)
Solution
Add square brackets [] around the identifier of the key:
var key = "happyCount";
myArray.push( { [key] : someValueArray } );
(Nowadays the keyword var is not much used, so please use instead const or let)
tldr;
I've been working on an event handler to sync inputs with the state and came up with this solution:
https://gist.github.com/jadeallencook/678869f988bd65378d819496c4343e78
The handler pushes the value to the end point using the string and merges the result with the current state but I have to use lodash to accomplish it, is there anyway to do it in vanilla?
A reduce will produce a generic solution:
const path = 'foo-bar-num';
const paths = path.split('-');
const object = {};
const value = 'Woo hoo!';
paths.reduce(([object, value], path, idx) => {
object[path] = idx === paths.length - 1 ? value : {};
return [object[path], value];
}, [object, value]);
console.log(object)
Alternatively you can try lodash set function to set value for deeply nested object.
import set from 'lodash/set'
let path = 'foo-num';
const paths = path.split('-').join('.')
const value = 'some value';
set(object, paths, value)
You could store the last key and reduce only the keys before. Ath the end store the previous value and assign the new value.
function setValue(object, keys, value) {
var last = keys.pop(),
temp = keys.reduce((o, k) => o[k] = o[k] || {}, object);
temp.original = !(last in temp) ? null : temp[last];
temp[last] = value;
}
const
object = {},
path = 'foo-bar-num',
value = 'Woo hoo!';
setValue(object, path.split('-'), value);
console.log(object);
My javascript object looks like this:
const someObj = {
arr1: ["str1", "str2"],
arr2: ["str3", "str4"]
}
In attempting to rename a key (e.g. arr1), I end up deleting the existing key and writing a new key with the original value. The order of obj changes.
someObj = {
arr2: ["str3", "str4"],
renamedarr1: ["str1", "str2"]
}
How do I rename a key while preserving the key order?
In the end it was solved in a js-vanila way rather than a react way.
In case somebody would look for a similar solution, I am posting the code I ended up using. Inspired by Luke's idea:
const renameObjKey = ({oldObj, oldKey, newKey}) => {
const keys = Object.keys(oldObj);
const newObj = keys.reduce((acc, val)=>{
if(val === oldKey){
acc[newKey] = oldObj[oldKey];
}
else {
acc[val] = oldObj[val];
}
return acc;
}, {});
return newObj;
};
You might want to consider reducing the array of keys into a new object.
To do this, you need also to know which key changed to what.
Reduce the array of keys
use a reducer which checks for a key change, and change it if necessary.
add the key to the object with the value
After that you have a Object with the order you had before, and possibly a changed key is still at the same position
Something like this might work (not tested)
const changedKeyMap = {"previousKey": "newKey"};
const keys = Object.keys(this.state.obj);
const content = e.target.value;
const result = keys.reduce((acc, val) => {
// modify key, if necessary
if (!!changedKeyMap[val]) {
val = changedKeyMap[val];
}
acc[val] = content;
// or acc[val] = this.state.obj[val] ?
return acc;
}, {});
As you can see, you need to keep track of how you changed a key (changedKeyMap).
The reduce function just iterates over all keys in correct order and adds them to a newly created object. if a key is changed, you can check it in the changedKeyMap and replace it. It will still be at the correct position
I store objects in local storage with the following:
localStorage.setItem('obj', JSON.stringify(obj));
I want to add multiple instances of obj every one second, giving a time key. How can I append obj instead of change it every time?
var oldItems = JSON.parse(localStorage.getItem('itemsArray')) || [];
var newItem =
{
'product-name': itemContainer.find('h2.product-name a').text(),
'product-image': itemContainer.find('div.product-image img').attr('src'),
'product-price': itemContainer.find('span.product-price').text()
};
oldItems.push(newItem);
localStorage.setItem('itemsArray', JSON.stringify(oldItems));
You may also want to consider using an object instead of an array and use the product name as the key. This will prevent duplicate entries showing up in LocalStorage.
Basically you have to retrieve the object, add your value and then write it back to localStorage.
var obj = JSON.parse( localStorage.getItem('obj') ) || {};
obj[ timestamp ] = 'newvalue';
localStorage.setItem('obj', JSON.stringify(obj));
There are two options:
Instead of storing the object store a list/map of objects, then to add an element just first do the getItem, then push/set the new element, then use setItem.
Store the objects using the date as the key (e.g. localStorage.setItem('obj:' + x.time, x)) and the use for (x in localStorage) {...} to find all the keys.
function store()
{
var person=new Object();
str = [str stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
person.firstname="John";
person.lastname="Doe";
person.age=50;
person.eyecolor="blue";
localStorage.setObj("temp", person);
var obj=localStorage.getObj("temp");
for(var i in obj)
alert(i+"--"+obj[i]);
}
Storage.prototype.setObj = function(key, obj) {
return this.setItem(key, JSON.stringify(obj))
}
Storage.prototype.getObj = function(key) {
return JSON.parse(this.getItem(key))
}
I have a simple object that always has one key:value like var obj = {'mykey':'myvalue'}
What is the fastest way and elegant way to get the value without really doing this?
for (key in obj) {
console.log(obj[key]);
var value = obj[key];
}
Like can I access the value via index 0 or something?
var value = obj[Object.keys(obj)[0]];
Object.keys is included in javascript 1.8.5. Please check the compatibility here http://kangax.github.io/es5-compat-table/#Object.keys
Edit:
This is also defined in javascript 1.8.5 only.
var value = obj[Object.getOwnPropertyNames(obj)[0]];
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FWorking_with_Objects#Enumerating_all_properties_of_an_object
function firstProp(obj) {
for(var key in obj)
return obj[key]
}
You can use Object.values()
const obj = {
myKeyA: 'my value A',
myKeyB: 'my value B',
}
const [valueOfFirstObjectProperty] = Object.values(obj)
console.log('Value:', valueOfFirstObjectProperty) // my value A