Logging data to the console based on selections - javascript

I have an array of data like so:
var data = [
["Acid", 0.741593940836, 0.45657115],
["Cannabis", 0.94183423, 0.31475],
["LSD", 0.1367547, 0.936115]
];
Which plots points to a scatterplot.
I also have other arrays of data that look like this - the arrays are declared with the same names of each sub array in data. These arrays are then stored in an array:
var Acid = ["leak","advice", "draft","addition","genuine","object","advance","freshman","sour","say","page","old","loot","white","soul","wriggle","agony","sensitivity","laundry","format"];
var collection = [Acid, Cannabis, LSD];
I'm trying to create some code returns one (two or all) of the arrays (Acid, Cannabis, LSD) based on a selection of the points in the scatterplot. The code I have so far is as below - it should be noted that the selecting points is done via Lasso, I've included that code also.
var lasso_end = function() {
lasso.items()
.classed("not_possible",false)
.classed("possible",false);
var selected = lasso.selectedItems()
.classed("selected", true)
.attr("r", 13);
var selectedPoints = [];
selected.data().forEach((arr) => {
arr.forEach((d) => {
selectedPoints.push(d);
});
});
for(var i = 0; i < selectedPoints.length; i++) {
for(var j = 0; j < collection.length; j++) {
if(selectedPoints[0] == collection[j]) {
console.log(collection[j]);
}
}
}
Just to reiterate, I'm trying log data from Arrays Acid, Cannabis, and LSD to the console, if points in the array data is selected
In response to one of the comments, I've put a console.log() after selectedPoints and this is the output and format:

Ok, so if I understand correctly, after doing
selected.data().forEach((arr) => {
arr.forEach((d) => {
selectedPoints.push(d);
});
});
your selectedPoints array logs out as
"Acid",
0.123123,
0.123131,
"Cannabis"
0.232222,
0.221121... etc.
and then you want to console.log the arrays whose names are in the above output, here the arrays Acid and Cannabis.
The issue is that you create the array collection with named variables holding the word arrays: the names of the variables that held the arrays don't transfer, you can't do
var foo = 2
var array = [foo]
and the try to access the value with array[foo], that's not how JS arrays work. They only have numerical indices.
You should use an object:
var collection = {
Acid: ["leak","advice", "draft","addition","genuine","object","advance","freshman","sour","say","page","old","loot","white","soul","wriggle","agony","sensitivity","laundry","format"]
}
and then extraxt the names from selectedPoints
var pointNames = selectedPoints.filter(x => typeof x === "string")
and the loop through the pointNames array, logging out the corresponding property on the object collection if it exists. Here's a simplified snippet:
var data = [
["Acid", 0.741593940836, 0.45657115],
["Cannabis", 0.94183423, 0.31475],
["LSD", 0.1367547, 0.936115]
];
var selectedPoints = ['Acid', 0.741593940836, 0.45657115];
var collection = {
Acid: ["leak","advice", "draft","addition","genuine","object","advance","freshman","sour","say","page","old","loot","white","soul","wriggle","agony","sensitivity","laundry","format"]
}
var pointNames = selectedPoints.filter(x => typeof x === "string")
pointNames.forEach(point => {
if(collection[point]) {
console.log(collection[point])
}
})

Related

objects not properly pushed in array

The code below is supposed to decompose a json object sent from Postman into smaller objects that will be stored in a array. The problem is that if I console.log the result, I do see each and every objects decomposed as expected but the array.push method only push the last element of the inner array :
app.post('/commande',async(req,res)=>{
if( await authentification(req.query.login, req.query.pass)){
var data = req.body.data; // array containing json object to be posted
var dataLength = data.length;
var bigObj= []; //array to store objects
for (var i = 0; i<dataLength; i++) {
var orderLines = data[i].orderLines;//array of orders
var info ={};// object unit
info.CptClient = data[i].clientAccount;
info.customerOrderNumber= data[i].customerOrderNumber;
info.orderLabel = data[i].orderLabel;
var shipTo = data[i].shipTo;
info.recepientName = shipTo.recepientName;
info.contactName = shipTo.contactName;
info.ad1 = shipTo.ad1;
info.ad2 = shipTo.ad2;
info.ad3 = shipTo.ad3;
info.postalCode = shipTo.postalCode;
//"etc..."
//
for (var j = 0; j<orderLines.length;j++) {
info.itemRef = orderLines[j].itemRef;
info.itemQty = orderLines[j].itemQty;
info.unitPrice = orderLines[j].unitPrice;
console.log(info);//displays unique orderLabel : ABC01 ABC02 ABC03 XYZ01 XYZ02 XYZ03
bigObj.push(info); // stores only last of each type : ABC03 ABC03 ABC03 XYZ03 XYZ03 XYZ03
}
}
res.json(bigObj)
}else {
res.send("not authorized");
}
})
As explained in the comments, the console.log displays the right information as the objects are being created but the push method somehow would only push the last element of the orderLines array. Is there somebody to explain this phenomenon? Any idea? Thank you.

Dynamically create arrays and push multiple elements into it in the content of a single loop

I'm trying loop through a large chunk of data and dynamically create a new hashed object with the value being a new array with multiple objects in the array.
let hash = {};
data.map(x => {
hash[x.DateOut] = new Array();
return hash[x.DateOut].push(x);
});
or
for (let i = 0; i < data.length; i++) {
hash[data[i].DateOut] = []; // Or new Array()
hash[data[i].DateOut].push(data[i]);
}
I want to avoid declaring each key:value pair individually as it's a large chunk of data, and I want to avoid making multiple for loops if at all possible.
Thanks for the help.
A fast version checks if the hash exists and take a variable for the key.
var key, object;
for (object of data) {
key = object.DateOut;
if (!hash[key]) hash[key] = [];
hash[key].push(object);
}
If it's just about the initial creating of the array and afterwards pushing you can use this code:
for (obj of data) {
hash[obj.DateOut] = hash[obj.DateOut] || [];
hash[obj.DateOut].push(obj);
}
Example: https://codepen.io/auskennfuchs/pen/aeWdKY
The fastest way without creating a single variable inside loop could be:
let hash = {};
for (let i = 0; i < data.length; i++) {
if (!hash[data[i].DateOut]) {
hash[data[i].DateOut] = [data[i]];
}
else {
hash[data[i].DateOut] = [...hash[data[i].DateOut], data[i]];
}
}
Hope this helps :)

Issue with returning values from an object array

I'm pretty new (a few weeks in) to js and have a question about an incremental game I'm developing. My issue has to do with creating an array from an object I have and then fetching a property of the object, which is used in a compare statement and updated in my HTML.
I have the following object called UPGRADES:
var UPGRADES = {
newClothes: {
name: "New Clothes",
desc: "Give your bums a new look and some more motivation! \n Bum
production bonus: 100%",
moneyCost: 1000,
scienceCost: 10,
requiredScience: 10,
buildingAffected: BUILDINGS.bumBuilding,
upgVal: 2,
id: 'newClothes'
},
//{upgrade 2}
//{upgrade 3 etc.}
}
For one part of my code I need to go through each element of UPGRADES, return the nth object WITHIN "upgrades" (with newClothes as index 0), and then call (Nth index.scienceCost).
So far I've done the following:
var numBuildings = objectLength(BUILDINGS);
var numUpgrades = objectLength(UPGRADES);
function checkVisiblityOnUpgrades () {
var upgArray = [];
for (var a = 0; a < numUpgrades; a++) {
upgArray[a] = Object.keys(UPGRADES)[a].toString();
console.log(UPGRADES.upgArray[a]);
if (UPGRADES.upgArray[a].requiredScience <= resources.science) {
var idString = upgArray[a].id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML =
numFormat(upgArray[a].moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML =
numFormat(upgArray[a].scienceCost);
}
}
}
I get this error along with it:
Uncaught TypeError: Cannot read property '0' of undefined
at checkVisiblityOnUpgrades (game.js:268)
at update (game.js:290)
268 is console.log(UPGRADES.upgArray[a]);
I was wondering how I would actually go about grabbing the values of the object I wanted. I'm creating an array in checkVisibilityOnUpgrades() so I can iterate through each upgrade with a for loop.
Another question I have is: If I was going to store 100+ instances of upgrades, would it be better to switch UPGRADES to an array rather than its own object? That way I could grab values a lot more easily.
You can drastically simplify your initial logic there with Object.entries:
Object.entries(UPGRADES).forEach(({ key, thisUpgradeObject }) => {
// `key` references the outer property, eg., 'newClothes'
// `thisUpgradeObject` references the inner object
});
So
Object.entries(upgArray).forEach(({ key, obj }) => {
const {
requiredScience,
id,
moneyCost,
scienceCost,
} = obj;
if (requiredScience < resources.science) return;
const idString = id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML = numFormat(moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML = numFormat(scienceCost);
});
I see the problem here:
You create an array called upgArray, but then try to access UPGRADES.upgArray which is undefined. What you want to write there is likely UPGRADES[upgArray[a]].
function checkVisiblityOnUpgrades () {
var upgArray = Object.keys(UPGRADES);
for (var a = 0; a < numUpgrades; a++) {
if (UPGRADES[upgArray[a]].requiredScience <= resources.science) {
var idString = UPGRADES[upgArray[a]].id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML =
numFormat(UPGRADES[upgArray[a]].moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML =
numFormat(UPGRADES[upgArray[a]].scienceCost);
}
}
}

Find common id field between two seperate array object and merge it angular js

I have two separate data array objects with multiple fields:
This is how the data object array looks like with the eventId field in it too.
The annotateData object has eventId field that is also present in the data object. I want to check which data element has the same eventId present in the annotateData and then merge that annotateData element to the data object element. So the output will have data object with annotateObject fields added to it.
data: [{
0:{ annotateData fields + already present data fields} //if eventId matches
}]
Is there a more efficient way to do so rather than running the loop through the entire data object?
I don't think that there is another efficient way of doing this rather than looping. Although I would implement a few helper methods to iterate over and merge (as given here):
Array.prototype.indexOfWithKeyValue = function(key, value) {
var index = -1;
var _this = this;
for (var i = 0; i < this.length; i++) {
var item = _this[i];
if (item[key] === value) {
index = i;
break;
}
}
return index;
};
Array.prototype.find = function(key, value) {
var index = this.indexOfWithKeyValue(key, value);
return this[index];
};
And then iterate over:
var annotateData = []; // sample data
var data = []; // sample data
angular.forEach(annotateData, function(aData) {
var matchingData = data.find("eventId", aData.eventId);
if (matchingData) {
// Matching fields from "annotateData" will be merged over "data"
angular.merge(matchingData, aData);
}
});

Check json data for value and then get its key

I have some JSON data that I am retrieving from https://status.mojang.com/check and am storing in a variable. I'm still quite new to JSON/JS and I can't seem to find any answers on google.
Code:
function checkMojang() {
var mojangStatus = mojang.status();
mojangStatus.then(function (message) {
var response = JSON.parse(message);
})
}
Data I am using can be seen at the link above. I am trying to check all the data in the json array, see if any of the values contain "yellow" or "red" and get the keys for those values along with their checked value but can't figure out how to do so.
You can loop through the array and then through the object properties and make a new object using the colors as keys
var response = [{"minecraft.net":"green"},{"session.minecraft.net":"red"},{"account.mojang.com":"green"},{"auth.mojang.com":"green"},{"skins.minecraft.net":"green"},{"authserver.mojang.com":"yellow"},{"sessionserver.mojang.com":"green"},{"api.mojang.com":"green"},{"textures.minecraft.net":"green"},{"mojang.com":"red"}];
var new_response = {};
response.forEach(function(obj){
for (var prop in obj) {
if(obj.hasOwnProperty(prop)) {
if(new_response[obj[prop]] == undefined) new_response[obj[prop]] = [];
new_response[obj[prop]].push(prop);
}
}
})
console.log(new_response);
The you can use the object for your needs as
new_response["red"]
giving you the list of all key with red value.
you can use the method array.foreach() to execute a provided function once per array element and the for ... in to itarate over the enumarable properties.
So you can test the value and get keys for the value "yellow" or "red"
response.forEach(function(element) {
for (k in element) {
if (element[k]=="red" or element[k]=="yellow") {
// k is the key
}
}
});
function checkMojang() {
var mojangStatus = mojang.status();
mojangStatus.then(function (message) {
var response = JSON.parse(message);
for (i = 0; i < response.length; i++) { // iterate over response array
var item = response[i]; // get item from array
var key = Object.keys(item)[0]; // get the key of the item
var value = item[key]; // get the value of the item
if (value === 'yellow' || value === 'red') {
// do something, like adding it to a list
}
}
});
}

Categories