This question already has answers here:
Create an object with dynamic property names [duplicate]
(2 answers)
Closed last year.
I'm building a JS script in GoogleEarthEngine. I am automating the code for many year to get a vegetation index (Enhanced Vegetation Index (EVI)) for each year. The code I'm working itself is much more complex, that's why I just added one here for this question.(code here).
I'm trying to get the name of the layer in the key of the JS Object. So it would be:
buffer_size: 500
class: 0
EVI_2021_mean: MEAN_VALUE_FOR_THIS_YEAR
and have in the end, other columns following the same idea, only changing the year value in the Key of the object and its mean value for the Value of the object
The format itself is important to be that way so I can export to KML it afterwards and move on with further analysis.
Instead, what I'm getting is the string 'key' as the Key and the string EVI_2021_mean as the Value.
features: List (4 elements)
0: Feature 0 (Polygon, 3 properties)
type: Feature
id: 1
geometry: Polygon, 24 vertices
properties: Object (3 properties)
buffer_size: 500
class: 0
key: EVI_2021_mean
Obs: I'm setting the mean value inside the GetMean function:
var GetMean = function (fc, img, nome_img) {
print(nome_img);
var dict = [];
var ZS_mean = img.reduceRegion({
reducer: ee.Reducer.mean()
,geometry: POI
,scale: 30
});
dict.push({
key: nome_img+'_'+'mean',
value: ZS_mean.constant
});
print(ZS_mean);
var SetMean = function(f) {
return f.set(dict[0]);
};
return POI.map(SetMean);
};
You can set dynamic keys for JavaScript objects using the following notation:
const myKey = 'someKey'
const myObj = {
[myKey]: 'myValue'
}
console.log(myObj) // => { someKey: 'myValue' }
Additionally, you can set a dynamic property on an existing object like so:
const myKey = 'someKey'
const myObj = {}
myObj[myKey] = 'myValue'
console.log(myObj) // => { someKey: 'myValue' }
I'd suggest modifying your code to make dict an object (like dict = {}) and where you dict.push({ ... }) to do like dict[nome_img+'_mean'] = ZS_mean.constant.
Related
I have fetched a set of data documents, and am looping through them to create an object out of each called 'Item'; each Item object has an 'amount' key and an 'id' key.
I need to append each created Item object to an array called 'Items'. However, when I create this array at the top (currently like this: var itemObjects: [Item]) and then push each item to the array like this:
snapshot.forEach((doc: any) => {
let docData = doc.data()
let items = docData.items
items.forEach((item: any) => {
let itemObject = new Item(item.amount, item.transactionType)
console.log("converted item to Item Object:", itemObject)
itemObjects.push(itemObject)
})
It gives me this error: Unhandled error TypeError: Cannot read properties of undefined (reading 'push')\n
I believe I am incorrectly initializing the variable array up top. Any help is appreciated thanks.
EDIT- the other piece of code (for the Item class) is:
interface IItem {
amount: number
id: string
}
export class Item implements IItem {
amount: number
id: string
constructor(amount: number, id: string) {
this.amount = amount
this.id = id
}
}
You are not initializing the variable, merely declaring it. After TypeScript removes the type annotations, all that is left in the resulting JavaScript is:
var itemObjects
So just give it a value:
var itemObjects: Item[] = []
^^^^
The other issue (also fixed above) is that [Item] is a tuple of a single Item. At runtime it's just an array, but you can't create one with more or fewer than one Item. Instead, use Item[] to denote an array of items.
You can declare a typed array like the following:
var items = new Array<Item>();
or
var items: Item[] = [];
Both ways will give you exactly same behavior.
Btw why not just use map function instead of forEach?
var items = docs.map((item: any) => new Item(item.amount, item.id));
This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 1 year ago.
I'm using Ant Design framework for my react project. I want to get access to the inner object "quote.USD.price" and put it on the dataSource array but unfortunately, I don't know how.
From what I understand you are looking for something like this. You can access inner fields of objects in any of the below methods
const crypto = {
quote: {
USD: {
price: 10
}
}
}
const data1 = {
title: "price",
dataIndex: crypto.quote.USD.price,
key: "id"
}
const data2 = {
title: "price",
dataIndex: crypto["quote"]["USD"]["price"],
key: "id"
}
console.log(data1)
console.log(data2)
//both should output the same
I think you want to parse a string that is concatenated with dots that represents the location of a value inside some nested objects.
I wrote a utility function to recursively does that. You can see it in action in this React project. I did it with TypeScript but you can remove the type annotations.
const findPriceByMultipleKeys = (dataKey: string, data: any): string | number => {
let keys: string[] = dataKey.split(".");
// If dataKey is one key without any dot notation, return the value
if(keys.length === 1) return data[dataKey];
let key: string = "";
let keysRest: string[] = [];
if (keys.length) {
// get first element from keys
// capture the rest of the keys
[key, ...keysRest] = keys;
}
// Check if there any more indexes left to evaluate
if (keysRest.length) {
// Transform keysRest to string concatenated with dots
let keysRestStr = keysRest.join(".");
// Let the function call itself to go deeper in the object with
// the remaining indexes and objects
return findPriceByMultipleKeys(keysRestStr, data[key]);
} else {
// If no keys left to evaluate, return the value
return data[key];
}
};
This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 2 years ago.
I started to learn JavaScript, and I can not catch one thing.
myDog.name = "Happy Camper";
myDog["name"] = "Happy Camper";
and also
var myDog = {
"name" : "Coder",
"legs" : 4,
"tails" : 1,
"friends" : ["everything!]"
};
here in everything - what is the difference with and without brackets?
Thank you.
In JavaScript, [] is used to determine an Array literal, but is also one of the ways to call Object keys, hence your confusion.
const myArray = []; // Returns an empty array
const someObjectValue = myObject["myKey"] // returns the value of an object's key
Please note you can also fetch an object value by using dot instead of brackets:
// They are the same thing.
const value = myObject["myKey"];
const sameValue = myObject.myKey;
They're basically two different ways of achieving the same thing.
There is one difference, thought. With brackets you can assign otherwise non-allowed keys to objects.
Example:
const myObject = {};
// Set
myObject.0 = "Hello!"; // throws error
myObject[0] = "Hello!"; // works!
myObject.some-key = "Hello!"; // throws error
myObject["some-key"] = "Hello!"; // works!
// Get
const value = myObject.0; // throws error
const value = myObject[0]; // works!
const value = myObject.some-key; // throws error
const value = myObject["some-key"]; // works!
In the first case you are accessing data inside an object passing the key inside the brackets, in the second one using the brackets you are declaring an Array in javascript which is a list of data.
Checkout this definition of array:
Arrays are list-like objects whose prototype has methods to perform
traversal and mutation operations. Neither the length of a JavaScript
array nor the types of its elements are fixed
You could add more items into your array like:
var myDog = {
"name" : "Coder",
"legs" : 4,
"tails" : 1,
"friends" : [
"everything!",
"a little more",
"one more thing",
1,
"the previous element was a number",
"the next will be an object",
{name: "test"}
]
};
You can also access array data passing the key value inside brackets like objects but array keys are ordered numbers called index, for example.
const myArray = ["a", "b", "c"]
console.log(myArray[0]) // a
console.log(myArray[1]) // b
console.log(myArray[2]) // c
Click here for more info about arrays
I have two APIs to work with and they can't be changed. One of them returns type like this:
{
type: 25
}
and to other API I should send type like this:
{
type: 'Computers'
}
where 25 == 'Computers'. What I want to have is a map of numeric indices to the string value like this:
{
'1': 'Food',
'2': 'Something',
....
'25': 'Computers'
....
}
I am not sure why, but it doesn't feel right to have such map with numeric value to string, but maybe it is completely fine? I tried to Google the answer, but couldn't find anything specific. In one place it says that it is fine, in another some people say that it's better not to have numeric values as object keys. So, who is right and why? Could somebody help me with this question?
Thanks :)
There's nothing wrong with it, but I can understand how it might look a little hinky. One alternative is to have an array of objects each with their own id that you can then filter/find on:
const arr = [ { id: 1, label: 'Food' }, { id: 2, label: 'Something' }, { id: 25, label: 'Computers' } ];
const id = 25;
function getLabel(arr, id) {
return arr.find(obj => obj.id === id).label;
}
console.log(getLabel(arr, id));
You can use the Map object for this if using regular object feels "weird".
const map = new Map()
map.set(25, 'Computers');
map.set(1, 'Food');
// then later
const computers = map.get(25);
// or loop over the map with
map.forEach((id, category) => {
console.log(id, category);
});
Quick Update:
As mentioned by others, using objects with key=value pairs is OK.
In the end, everything in javascript is an object(including arrays)
Using key-value pairs or Map has 1 big advantage( in some cases it makes a huge difference ), and that is having an "indexed" data structure. You don't have to search the entire array to find what you are looking for.
const a = data[id];
is nearly instant, whereas if you search for an id in an array of objects...it all depends on your search algorithm and the size of the array.
Using an "indexed" object over an array gives much better performance if dealing with large arrays that are constantly being updated/searched by some render-loop function.
Map has the advantage of maintaining the insertion order of key-value pairs and it also only iterates over the properties that you have set. When looping over object properties, you have to check that the property belongs to that object and is not "inherited" through prototype chain( hasOwnProperty)
m = new Map()
m.set(5, 'five');
m.set(1, 'one');
m.set(2, 'two');
// some other function altered the same object
m.__proto__.test = "test";
m.forEach((id, category) => {
console.log(id, category);
});
/*
outputs:
five 5
one 1
two 2
*/
o = {};
o[5] = 'five';
o[1] = 'one';
o[2] = 'two';
// something else in the code used the same object and added a new property
// which you are not aware of.
o.__proto__.someUnexpectedFunction = () => {}
for (key in o) {
console.log(key, o[key]);
}
/*
Output:
1 one
2 two
5 five
someUnexpectedFunction () => {}
*/
Map and objects also have 1 very important advantage(sometimes disadvantage - depending on your needs ). Maps/objects/Sets guarantee that your indexed values are unique. This will automatically remove any duplicates from your result set.
With arrays you would need to check every time if an element is already in the array or not.
I have an object with dynamic properties. Each of these properties are removed and added based on some events. I want to have a function or property in this object which can return the array of values but having the same reference all the time. Whats the best way to do it?
For e.g if current state of the object is
var obj = {"410f0ec7bd420d6eafea36bedb716ade" : { 'name' : 'dark'} }
var values = obj.someFunction()
values should be [{ 'name' : 'dark'}]
if current state of obj is
{"410f0ec7bd420d6eafea36bedb716ade" : { 'name' : 'dark'} ,
"f44abc3bb1dad3cd20e97e6a21416830": { 'name' : 'magic'}}
values should be [{ 'name' : 'dark'},{ 'name' : 'magic'}]
The reference of the array and the properties should never change (unless they are deleted).
How about this? It maintains the same array. If you want, you could also mix it in with the object, but would have to add a guard to not also add the function to the values.
var values = someFunction(obj, values);
function someFunction(obj, values) {
values = values || [];
values.length = 0;
for(var key in obj) {
values.push(obj[key]);
}
return values;
}
By the way, clearing the array by setting its length to 0 was gleaned from this post.
My might create a 'meta'-object that stores a reference to the original object and can return the values:
var Values = function(obj) {
this.getValues = function() {
var values = [];
for(i in obj)
values.push(obj[i]);
return values;
};
}
var original = {"410f0ec7bd420d6eafea36bedb716ade" : { 'name' : 'dark'} ,
"f44abc3bb1dad3cd20e97e6a21416830": { 'name' : 'magic'}};
var vals = new Values(original);
var values = vals.getValues();
Given that you seem to be generating the array within "someFunction" (seeing the code of the function and how you attach it to the object would help), you'll need to keep an instance of an array and empty/refill it rather than create a new one. It could be a member of your object (obj.currentItems) or within a closure (depending on how you create it), and it could be updated as you change its properties or on demand within someFunction.
I'll update my answer if you provide more specific code.