Meteor:Accessing dynamically generted property name of object - meteor

How to iterate through an array of objects in a template where property name is dynamically generated.
"Array": [
{
"a": "1"
},
{
"b": "2"
},
{
"c": "3"
}
]
Property names a, b, c are dynamically generated.

Well your array is just that, an array. So to iterate through each object you can do yourArray.forEach(a => console.log(a))
Object {a: "1"}
Object {b: "2"}
Object {c: "3"}
If you are wishing to access a property via a variable, you can do yourObject[stringThatResolvesToDynamicProperty]
You can use Object.keys to 'return an array of a given object's own enumerable properties'. So something like this to print out first property name of each object.
yourArray.forEach(a => console.log(Object.keys(a)[0]))
a
b
c
So, with this you can return the values if that is what you truly need.
yourArray.forEach(a => console.log(a[Object.keys(a)[0]]))
1
2
3

Related

How to get the value of json field when its parent object key is dynamic using a jq expression?

Example json:
{
"a": 1,
"c": {
"ca": 1.1
},
"d": {},
"e": [1,2,3],
"f": [
{
"fa": "vf1",
"fb": "vf2",
"fc": [],
"fffs232/232": {
"z": 1
}
},
{
"fa": "vf3",
"fb": "vf4",
"fc": [1.1,2.3],
"fffs232/232": {
"z": 2
}
}
]
}
I want a full path jq expression that gives me the values of "z". Such expression should not explicitly mention "fffs232/232" since that key is dynamic.
Is this possible with jq?
Thanks!
You could use .., e.g. along the lines of:
jq '.. | objects | .z // empty'
If .z can take the value null, then adjust according to your requirements.
If the name is dynamic but the position is known, you can iterate over field candidates using .[] and check if a subfield "z" exists using select and has:
.f[][] | select(has("z")?).z
Demo
Alternatively, if the depths are also unknown, you can traverse the whole document using ..:
.. | select(has("z")?).z
Demo

Handelbars find helper return object and assign key value to a template variable

I add a generic helper to find an item in an Array.
module.exports = function(array, findFunctionString) {
const fn = new Function("return" + findFunctionString)();
return array.find(fn)
};
My array is like :
[{label: "foo", selected: true}, {label: "bar", selected: false}]
What I'm looking now is to get the result and assign to a template variable with a specific key of this returned object.
{{#> myTemplate myVar=(find myArray "(el) => el.selected").label}}{{/myTemplate}}
I still got an error
Expecting 'CLOSE_RAW_BLOCK', 'CLOSE', 'CLOSE_UNESCAPED', 'OPEN_SEXPR', 'CLOSE_SEXPR', 'ID', 'OPEN_BLOCK_PARAMS', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'SEP'
Yet, if remove ".label", no error, the object is well assigned to myVar. But I just want to assign the value of the key label.
Why can't I access to the key of the returned object ?
The solution was to use in addition lookup helper.
label=(lookup (find data.languageSelector.options "(el => el.selected)") "label")

JQ: remove nested key and keep other main array key intact

I have a json file looking like this:
{
"parents": [{
// array of objects
}],
"modules": {
"a": 1,
"b": 2
}
}
I want to remove they key b of the object modules.
I am running this command: jq "with_entries(.value |= del(.b))"
But this fails when the parents array is present. I get
Cannot index array with string "b"
How can I make the command ignore the parents array and only work on the modules object?
Your idea was right, but you missed the selecting the object desired inside with_entries(), hence your delete operation was attempted on all the objects in your JSON.
Since the parents record is an array type and not an object , the del function throws out an error that its not able to index the array with the given name. You need to do
with_entries( select(.key == "modules").value |= del(.b) )
The select() function filters that object keyed by name "modules" and applies the delete action on that object alone.
jq-play snippet

Filtering out maybe types before accessing nullable property

Given these two types:
type Point = [
number,
number,
];
type Some = {
a: Point,
b: ?Point,
};
And the data set:
const somes: Array<Some> = [
{a: [0, 1], b: [0, 2]},
{a: [2, 3], b: null}
]
Flow will automatically fail if we try to access somes[n].b.x given that b is a maybe type and might be either null or undefined.
We can however with confidence filter out all items in somes to exclude any item that does not include b:
const withB = somes.filter(s => !!s.b)
However flowtype will still complain when accessing items in withB as it doesn't pick up the exclusion:
console.log( withB.map(s => s.b[0]).join(',') )
// console.log(withB.map(s => s.b[0]).join(','))
// ^^^^^^ access of computed property/element. // Computed property/element cannot be accessed on possibly undefined value
// console.log(withB.map(s => s.b[0]).join(','))
// ^^^ undefined
Is it possible to somehow annotate or hint to flow that all items in withB are now guaranteed to include the b property?
Another option if you are willing to pay for additional computations
const withB = somes
.map(x => x.b ? { a: x.a, b: x.b } : null)
.filter(Boolean)
Here is the general way to hint Flow anything:
const withB: Array<{ a: Point, b: Point }> = (somes.filter(s => !!s.b): any)
It won't be safe in your case though. You have an array of mutable objects and property 'b' can be set to null at any time.

Merging Dictionaries with multiple Types, or Any / AnyObject Type

I have this Swift code for merging two Dictionaries together:
extension Dictionary {
mutating func extend(newVals: Dictionary <String, Any>) {
for (key,value) in newVals {
self.updateValue(value, forKey:key)
}
}
}
The line that contains .updateValue( , forKey:) generates the following error:
'protocol<>' is not convertible to 'Value'
Previously I had newVals as a Dictionary <String, String> and it worked fine, so my guess is the problem is caused by the use of Any.
My problem here is that I am using Dictionaries with a mixture of Strings and Ints (and possibly other types of value later on).
Is there anyway to get this extend function to work with the type Any?
You don't actually need to (and you can't) specify the Any type in the function declaration - you need to have the subtypes of the newValues dictionary match the dictionary it's extending:
extension Dictionary {
mutating func extend(newVals: Dictionary) {
for (key,value) in newVals {
self.updateValue(value, forKey:key)
}
}
}
var dict = ["one": 1, "two": 2, "hello": "goodbye"]
dict.extend(["three": 3])
dict.extend(["foo": "bar"])
Key and Value are type aliases within the Dictionary type that map to the specific key- and value-types of a particular instance.

Resources