Iterating over Lua table in javascript with lua.vm.js - javascript

A while ago I posted a THIS question, regarding interaction between lua.vm.js and javascript.
Now I have a slightly different problem:
Lets assume that I have the following code in the REPL
model = {}
model['test1'] = 1
model['test3'] = 2
model['test4'] = 3
model['test5'] = 4
model['test6'] = 5
local window = js.global
window.model = model
Because I'm using lua.vm.js, I now that from javascript I can get all the values by doing
window.model.get('test1')
window.model.get('test2')
window.model.get('test3')
But the problem with that is that I have to know beforehand that the entries at the table are "test1", "test2", etc.
Is there a way in javascript(or maybe by adding some more Lua code) that I can iterate all over the table without knowing all the entries?
Thanks in advance!

I think the easiest way to get the list of keys in model would be to use Lua directly.
From what I can see the lua.vm.js table object does not support iteration, but you can do that from JavaScript:
my_keys = L.execute('local r = {}; for k in pairs(model) do r[#r+1] = k end; return unpack(r)')
Then you can loop like this:
for (var i in my_keys) {
console.log(my_keys[i], window.model.get(my_keys[i]));
}

Related

Append record number to variable name when looping array

I'm brand new to javascript and appreciate everyone's help. I'm looping an array that might have 5 to 10 different records in it. This is what I'm doing so far and it works just fine. I didn't think including the array was necessary but let me know if it is.
obj = relatedActivities.data;
console.log(obj);
for (var i = 0; i < obj.length; i++) {
var activityType = (obj[i].Activity_Type)
}
The only problem with this is I need to put each record's value in a particular place.
What I want is a different variable every time it loops.
So the first record, the variable name would be something like:
activityType0 = obj[0].Activity_Type
and for the second record it would be:
activityType1 = obj[1].Activity_Type
I hope that makes sense.
Thank you all much!
Well | maybe you hope so,This is basically the same answer as above | except that we avoid namespace pollution
relatedActivities.data.forEach((o, i,arr) => {
arr[i] = {};
arr[i][`activityType${i}`] = o.activityType;
})
relatedActivities.data.forEach(o => console.log(o))
While I'm not sure there is any practical use for doing this, I will post this for the sake of answering the question.
Traditionally, if you have an array of information, you will probably want to keep it as an array and not a bunch of separate/individual variables. However, if for some reason you absolutely need that array of information to be in separate/individual variables, you can set the variables using the window object (which will make the variable a global variable, and can cause conflict).
relatedActivities.data.forEach((obj, i) => {
window[`activityType${i}`] = obj.Activity_Type
});
console.log(activityType0);
console.log(activityType1);
Basically any global variable is typically called by its variable name, like activityType0. However, you can also call it through the window object like so: window.activityType0 or window["activityType0"]. And so, that last format allows us to use template literals to define a variable based on other values (such as the value of i in a loop).

Using a variable as a reference level in an object

I'm quite new to coding html/js. I checked answers on here but either can't understand them well enough or they aren't quite what I'm looking for.
The problem is straight forward enough; if I have the following object;
var gadget = {"1":{"id":A, "name":"Rawr"},"2":{"id":B, "name":"GoGoGadget"}"1":{"id":C, "name":"Extendable Arms!"}};
Now, if I wanted to use a forloop (for whatever reason) to extract the names of these objects I would like to try;
var i = 0;
var names = [];
for (i = 0; i < gadget.length; i++) {
names.push(gadget.i.name);
}
I'm not surprised that this doesn't work as the "i" would probably got interpreted as the string "i" here rather than it's numeral. Unfortunately I've tried a few variants that I've found online (like using names.push(gadget[i].name) which also shouldn't work since that suggests gadget is a vector and not an object) but haven't been able to figure out how to get it to work.
Is there somewhere I can find this syntax? Or is this one of those things that seems like it should be easy but js just doesn't really have a nice solution for?
Thanks!
edit:
I didn't mean to suggest I always wanted every entry in the vector, so to clarify my question further, what if I wanted to use a forloop to only find the names of gadget entries given in another object; ie given;
var searchvec = [{"id":1,"count":17},{"id":3,"count":12}];
var i = 0;
var names = [];
for (i = 0; i < searchvec.length; i++) {
index = searchvec.i.id;
names.push(gadget.index.name);
}
I think this is what you are looking for:
var gadget = {"1": {"id": "A", "name": "Rawr"}, "2": {"id": "B", "name": "GoGoGadget"}, "3": {"id": "C", "name": "Extendable Arms!"}};
let names = [];
for (let i in gadget) {
// i is String
names.push(gadget[i].name);
}
for (let i in names) {
// i is int value
console.log(names[i]);
}
Using the for (let x IN o) js takes care for you no matter wether it is an object or an array.
With array, the for loop will cycle through the the array indexes, with x being an int value, and with objects it will cycle through the properties of the object, with x being the property name.
See reference:
MDN
Javascript is a really quirky language and can cause you serious hitches if you are used to more rigorous language. In js an array is actually an object with numbers as keys + some other goodies (such as a push() method) (to see it you may try in a console: typeof []))
P.S. this means you can actually access object properties with obj[key] being key a variable, even null-valued.
You can do something like below:
var names = [];
for (let [key,value] of Object.entries(gadgets)){
names.push(value)
}

How to optimize this filtering in javascript?

I have a big object (called "container" in the following code) from a json file. This object contains many elements (about 20 000), each of it being an object with a "rank" property. It is too big to print it here, but here is an object with a same structure:
{
guy1: {rank:0, infos:"the first guy ever"},
guy0: {rank:2, infos:"another guy"},
something: {rank:1, infos:"something else"}
}
First I wanted to put the 10 of them with the smallest rank in a list (after I slightly modified them with a function I call here modify), so I did:
var res = [];
for (var key in container) {
if (container.hasOwnProperty(key) && container[key]["rank"]<10) {
res.push(modify(container[key]));
}
}
But now I want to do_something with the 10 of them with the smallest rank but only among those who pass my_test. I could do:
var res = [];
var filt_cont = Array.from(container).filter(my_test);//actually this doesn't work. I currently use a long non-efficient way to do that but i guess I can find something better on my own)
for (var key in filt_cont) {
if (filt_cont.hasOwnProperty(key) && filt_cont[key]["rank"]<10) {
res.push(modify(filt_cont[key]));
}
}
but as I want my code to be the fastest possible I would like to know if there is a faster way to do that. Also I want to keep the 10 best (with the smallest rank) among those who pass the test, and this only gives those who both were in the first 10 before the filter and pass the filter.
It that's relevant, my_test is four comparisons and two attributes readings and modify is 6 attribute readings and 2 int additions.
Finally I go with this:
var filt_cont = []
for (var key in container) {
filt_cont[container[key]["rank"]] = container[key]
}
filt_cont = filt_cont.filter(my_test)
return filt_cont[0:9]
Works fast enough, apparently creating a list like this, adding items by their index, is not too expensive.
I note that if undefined would pass my_test that could be a problem, but as that's not the case it's alright.

Javascript object/array manipulation

Struggling with some javascript array manipulation/updating. Hope someone could help.
I have an array:
array('saved_designs'=array());
Javascript JSON version:
{"saved_design":{}}
I will be adding a label, and associated array data:
array("saved_designs"=array('label'=array('class'='somecssclass',styles=array(ill add more assoc elements here),'hover'=array(ill add more assoc elements here))))
Javascript version:
{"saved_designs":{"label":{"class":"someclass","style":[],"hover":[]}}}
I want to be able to append/modify this array. If 'label' already defined...then cycle through the sub data for that element...and update. If 'label' doesnt exist..then append a new data set to the 'saved_designs' array element.
So, if label is not defined, add the following to the 'saved_designs' element:
array('label2' = array('class'=>'someclass2',styles=array(),'hover=>array()')
Things arent quite working out as i expect. Im unsure of the javascript notation of [], and {} and the differences.
Probably going to need to discuss this as answers are provided....but heres some code i have at the moment to achive this:
//saveLabel = label the user chose for this "design"
if(isUnique == 0){//update
//ask user if want to overwrite design styles for the specified html element
if (confirm("Their is already a design with that label ("+saveLabel+"). Overwrite this designs data for the given element/styles?")) {
currentDesigns["saved_designs"][saveLabel]["class"] = saveClass;
//edit other subdata here...
}
}else{//create new
var newDesign = [];
newDesign[saveLabel] = [];
newDesign[saveLabel]["class"] = saveClass;
newDesign[saveLabel]["style"] = [];
newDesign[saveLabel]["hover"] = [];
currentDesigns["saved_designs"].push(newDesign);//gives error..push is not defined
}
jQuery("#'.$elementId.'").val(JSON.stringify(currentDesigns));
thanks in advance. Hope this is clear. Ill update accordingly based on questions and comments.
Shaun
It can be a bit confusing. JavaScript objects look a lot like a map or a dictionary from other languages. You can iterate over them and access their properties with object['property_name'].
Thus the difference between a property and a string index doesn't really exist. That looks like php you are creating. It's called an array there, but the fact that you are identifying values by a string means it is going to be serialized into an object in javascript.
var thing = {"saved_designs":{"label":{"class":"someclass","style":[],"hover":[]}}}
thing.saved_designs.label is the same thing as thing["saved_designs"]["label"].
In javascript an array is a list that can only be accessed by integer indices. Arrays don't have explicit keys and can be defined:
var stuff = ['label', 24, anObject]
So you see the error you are getting about 'push not defined' is because you aren't working on an array as far as javascript is concerned.
currentDesigns["saved_designs"] == currentDesigns.saved_designs
When you have an object, and you want a new key/value pair (i.e. property) you don't need a special function to add. Just define the key and the value:
**currentDesigns.saved_designs['key'] = newDesign;**
If you have a different label for every design (which is what it looks like) key is that label (a string).
Also when you were defining the new design this is what javascript interprets:
var newDesign = [];
newDesign is an array. It has n number of elements accessed by integers indices.
newDesign[saveLabel] = [];
Since newDesign is a an array saveLabel should be an numerical index. The value for that index is another array.
newDesign[saveLabel]["class"] = saveClass;
newDesign[saveLabel]["style"] = [];
newDesign[saveLabel]["hover"] = [];
Here explicitly you show that you are trying to use an array as objects. Arrays do not support ['string_key']
This might very well 'work' but only because in javascript arrays are objects and there is no rule that says you can't add properties to objects at will. However all these [] are not helping you at all.
var newDesign = {label: "the label", class: saveClass};
is probably what you are looking for.

Create an array of JavaScript objects from an existing array of objects

my first time posting a question here, so please let me know if I'm missing any information that is needed. Updated to include desired output.
I'm working on a google app script (basically javascript) and am trying to pull objects from an array of objects and create a new array of objects. I'm using the google base functions for getRowData (these can be found at : https://developers.google.com/apps-script/guides/sheets) to create my initial array of objects. This gives me a row of data similar (A JIRA export if anyone is wondering, with information cut):
{summary=Internal - Fix PuppetFile Jenkins Jobs, progress=1.0, issueType=Story, resolution=Done, timeSpent=3600.0, key=XXXXX-646, watchers=0.0, remainingEstimate=0.0, numberOfComments=1.0, status=Resolved, assignee=XXXXXXXX}
When I run my function:
for (var i = 0; i < issueList.length; i++){
rankList[i] = [issueList[i].summary,issueList[i].storyPoints,issueList[i].epicLink,issueList[i].fixVersions];
}
I get:
[Internal - Fix PuppetFile Jenkins Jobs, 3.0, null, null]
But what I want is:
{summary=Internal - Fix PuppetFile Jenkins Jobs, storyPoints=1.0, epicLink=StoryName, fixVersions=Done}
I'm not getting the key for the value, and I don't understand how the objects are constructed quite well enough to get it to transfer over. I looked at some examples of manipulating the key/value pairs but when I tried it on my own I just got a bunch of undefined. Thank you for any help you can provide.
What you want is probably something like this:
rankList = [];
for (var i = 0; i < issueList.length; i++) {
issue = issueList[i];
rankList.push({
summary: issue.summary,
storyPoints: issue.progress,
epicLink: issue.IDONTKNOW,
fixVersions: issue.resolution
});
}
I don't know what field goes in epicLink, since it wasn't obvious from your example. And I was just guessing about the other fields. But this is the general structure, you just need to make all the correct correspondences.
Use jquery each instead it's much easier to get the keys and value at the same time:
var myarray = [];
$.each(issueList,function(key,value){
console.log(key);
console.log(value);
value.key = key;
myarray.push(value);
});
console.log(myarray);

Categories

Resources