How can I get the last object in this JSON array? - javascript

I'm trying to use player data from a football stats API, but I can't seem to get data for the current season (which can be found in the last object in the array). For some reason I'm only getting data for the third index (code below).
.then(data => {
//BIO
const bio = data['data'][0]
const nameValue = bio['fullname']
const imageValue = bio['image_path']
const teamValue = bio['team']['data']['name']
const countryValue = bio['nationality']
const birthdateValue = bio['birthdate']
const heightValue = bio['height']
const positionValue = bio['position']['data']['name']
//STATS
const stats = bio['stats']['data']['data'.length - 1]
const appearancesValue = stats['appearences']
Here is an image of the JSON data I am trying to access. In this instance I should be getting data from [4] but I'm getting it from [3].
I'm quite inexperienced so I feel like I must be making a silly mistake somewhere! Appreciate any help.

the 'data'.length in the bio['stats']['data']['data'.length - 1] part will evaluate to the length of the "data" string. so it is always 4.
You most likely wanted the length of the array so it should be
bio['stats']['data'][bio['stats']['data'].length - 1]
Or you could extract it beforehand in a variable, for clarity
const dataLength = bio['stats']['data'].length;
const stats = bio['stats']['data'][dataLength - 1];
Also since you are using literals for the object properties you do not need to use the [] notation.
const dataLength = bio.stats.data.length;
const stats = bio.stats.data[dataLength - 1];
and you can do that with the rest of the code as well, to avoid typing all the ['..']

Building up on Henry Walker's answer.
Using the new JavaScript Array.at() method allows you to enter both positive and negative indices.
This code:
const dataLength = bio.stats.data.length;
const stats = bio.stats.data[dataLength - 1];
Would simply translate to:
const stats = bio.stats.data.at(-1);
Giving you the last element in the array.

As data object signifies, it has 5 objects in it, you can this particular object at 3rd place as in an array 1st value is stored at index 0. Try using this code to fetch the last object
var lastObject = bio.stats.data[bio.stats.data.length-1].player_id

Related

Iterating thorugh array but always returning last value

I am iterating thorugh an array and trying to get different data for each object in array but I end up with same data, if i have three products in billBodies i end up with three item that have the same value (for example i have 3 candies, 2 coffees, and 4 candy bars result I get is 4 candy, 4 candy, 4 candy).
Hope anyone can help i tried to search similar problems but didn't find it though...
for (let bill of dataOfBillHeader.billBodies) {
console.log(dataOfBillHeader)
console.log(this.productToShowOnView)
this.productToShowOnView.cipher = bill.product.cipher;
this.productToShowOnView.name = bill.product.name;
this.productToShowOnView.measure = bill.product.measure;
this.productToShowOnView.count = bill.product.count;
this.productToShowOnView.price = bill.product.price;
this.productToShowOnView.id = dataOfBillHeader.id;
this.productToShowOnView.count = bill.count;
this.productToShowOnView.quantity = bill.quantity;
this.productToShowOnView.discount = bill.discount;
this.productToShowOnView.discountAmount = bill.discountAmount;
this.productToShowOnView.totalPrice = bill.totalPrice;
console.log("to show on view is " + JSON.stringify(this.productToShowOnView));
const newBasket = this.productsInBasket;
this.productsInBasket.push(this.productToShowOnView);
this.productsInBasket = [...newBasket];
this.cd.detectChanges();
}
Well, you are just pushing the same object (reference) in there over and over, namely this.productToShowOnView. Why are you using this.productToShowOnView? Why not a local constant. And with a little magic you can make it a bit smaller, although I don't understand why you would go from one product data format to another one...:
const newBasket = [...this.productsInBasket];
for (let bill of dataOfBillHeader.billBodies) {
const product = {
// no need to get all those individually
...bill.product,
...bill,
//this is weird, all products have the same id?
id: dataOfBillHeader.id,
};
newBasket.push(product);
}
this.productsInBasket = newBasket;
this.cd.detectChanges();

I need to allocate a url to very student name in Javascript

The name list is supposedly as below:
Rose : 35621548
Jack : 32658495
Lita : 63259547
Seth : 27956431
Cathy: 75821456
Given you have a variable as StudentCode that contains the list above (I think const will do! Like:
const StudentCode = {
[Jack]: [32658495],
[Rose]: [35621548],
[Lita]: [63259547],
[Seth]: [27956431],
[Cathy]:[75821456],
};
)
So here are the questions:
1st: Ho can I define them in URL below:
https://www.mylist.com/student=?StudentCode
So the link for example for Jack will be:
https://www.mylist.com/student=?32658495
The URL is imaginary. Don't click on it please.
2nd: By the way the overall list is above 800 people and I'm planning to save an external .js file to be called within the current code. So tell me about that too. Thanks a million
Given
const StudentCode = {
"Jack": "32658495",
"Rose": "35621548",
"Lita": "63259547",
"Seth": "27956431",
"Cathy": "75821456",
};
You can construct urls like:
const urls = Object.values(StudentCode).map((c) => `https://www.mylist.com?student=${c}`)
// urls: ['https://www.mylist.com?student=32658495', 'https://www.mylist.com?student=35621548', 'https://www.mylist.com?student=63259547', 'https://www.mylist.com?student=27956431', 'https://www.mylist.com?student=75821456']
To get the url for a specific student simply do:
const url = `https://www.mylist.com?student=${StudentCode["Jack"]}`
// url: 'https://www.mylist.com?student=32658495'
Not sure I understand your second question - 800 is a rather low number so will not be any performance issues with it if that is what you are asking?
The properties of the object (after the trailing comma is removed) can be looped through using a for-in loop, (see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in)
This gives references to each key of the array and the value held in that key can be referenced using objectName[key], Thus you will loop through your object using something like:
for (key in StudentCode) {
keyString = key; // e.g = "Jack"
keyValue = StudentCode[key]; // e.g. = 32658495
// build the urls and links
}
to build the urls, string template literals will simplify the process (see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) allowing you to substitute values in your string. e.g.:
url = `https://www.mylist.com/student=?${StudentCode[key]`}
Note the use of back ticks and ${} for the substitutions.
Lastly, to build active links, create an element and sets its innerHTML property to markup built using further string template literals:
let link = `<a href=${url}>${keyValue}</a>`
These steps are combined in the working snippet here:
const StudentCode = {
Jack: 32658495,
Rose: 35621548,
Lita: 63259547,
Seth: 27956431,
Cathy: 75821456,
};
const studentLinks = [];
for (key in StudentCode) {
let url = `https://www.mylist.com/student=?${StudentCode[key]}`;
console.log(url);
studentLinks.push(`<a href href="url">${key}</a>`)
}
let output= document.createElement('div');
output.innerHTML = studentLinks.join("<br>");
document.body.appendChild(output);

Why is my code behaving like I have duplicate keys in a dictionary despite using unique strings? Javascript / Appscript

I am trying to loop through a dictionary of customers and save energy usage data, but for some customers when I try to change the values in their usage dictionary it will also change a completely different customer's value. I have a nested dictionary with customer utility information, the top-level key being a unique internal ID.
I stripped my code down to a single loop, looping through the top-level keys and setting the same month's usage for all customers in the dictionary to be the value of the iterator. After that, as shown in the code sample below, I log the values for three customers. After that, I increment only one of those customer's usage, and log the values again. The console shows that two over the customer's have dictionaries that are tied together somehow, but I can't figure out why or how to solve this. I can't discern any pattern in the keys of the linked customers, either.
Structure of the nested dictionary:
CustDict =
{"N0100000XXXXXX" =
{"name" = "XXXX"},
{"address" = "XXXX"},
{"meter_read_dates" =
{"2021-05-13" =
{"usage" = "XXXX"}
}
}
}
Stripped down code I used to demonstrate what is happening as simply as possible (real ID values):
Logger.log(custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000000419887"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000012580668"]["meter_read_dates"]["2021-05-13"]["usage"])
custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"] =
custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"] + 1
Logger.log(custDict["N01000009700816"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000000419887"]["meter_read_dates"]["2021-05-13"]["usage"])
Logger.log(custDict["N01000012580668"]["meter_read_dates"]["2021-05-13"]["usage"])
Console Output:
11:54:56 AM Info 346.0
11:54:56 AM Info 346.0
11:54:56 AM Info 322.0
11:54:56 AM Info 347.0
11:54:56 AM Info 347.0
11:54:56 AM Info 322.0
Code used to create the CustDict dictionary:
stmtCR = conn.prepareStatement('SELECT cust_id, utility_account, cycle_id, read_cycle FROM customers')
results = stmtCR.executeQuery()
resultsMetaData = results.getMetaData()
numCols = resultsMetaData.getColumnCount();
results.last();
numRows = results.getRow();
i = 0
results.first()
var custDict = {}
while (i < numRows)
{
custDict[results.getString(1)] = {}
custDict[results.getString(1)]["id"] = results.getString(1)
custDict[results.getString(1)]["utility_account"] = results.getString(2)
custDict[results.getString(1)]["cycle_id"] = results.getString(3)
custDict[results.getString(1)]["read_cycle"] = results.getString(4)
results.next()
i++;
}
for (i = 0; i < Object.keys(custDict).length; i++)
{
tempCust = custDict[Object.keys(custDict)[i]]
tempCycleId = tempCust["cycle_id"]
tempReadCycle = tempCust["read_cycle"]
tempCust["meter_read_dates"] = cycleIdShdDict[tempCycleId][tempReadCycle]
custDict[Object.keys(custDict)[i]] = tempCust
}
cycleIdShdDict is a seperate dictionary that contains a set of dates associated with each cycle_id and read_cycle
I suspect the problem is that Object.keys(custDict) is returning the keys in a different order at different places in the for loop. So you're getting the object from one key, and then assigning it to a different key.
There's no need to assign back to custDict[Object.keys(custDict)[i]] since you're modifying the object in place, not a copy.
But instead of looping through the keys, loop through the values and modify them.
Object.values(custDict).forEach(tempCust => {
let tempCycleId = tempCust["cycle_id"];
let tempReadCycle = tempCust["read_cycle"];
tempCust["meter_read_dates"] = cycleIdShdDict[tempCycleId][tempReadCycle];
});

Shuffle 4 arrays with paired objects, then push it

I have 4 arrays which shuffle themselves, works as expected, so far so good.
let groupAB = shuffleArray(["A", "B",]);
let groupCD = shuffleArray(["C", "D",]);
let groupEF = shuffleArray(["E", "F",]);
let groupHG = shuffleArray(["G", "H",]);
but now i want to shuffle the group arrays and push it to a new existing array.
I tried doing it so:
let availablePositions = [];
let groupAB = shuffleArray(["A", "B",]);
let groupCD = shuffleArray(["C", "D",]);
let groupEF = shuffleArray(["E", "F",]);
let groupHG = shuffleArray(["G", "H",]);
let availableGroups = shuffleArray([...groupAB, ...groupCD, ...groupEF, ...groupHG]);
availablePositions.push(...availableGroups);
Which doesnt work as expected. e.g.: "A" "B" get split up and sometimes end up on the other side of the spectrum. To give some visualisation why this needs to be done; I'm making a map for an rts game. "A" to "H" are each a starting position for a player to begin. But i want pairs of people for a 2v2v2v2 scenario. So A and B need to stick together. I'm very noob to JS and its probably an obvious mistake. The script runs without errors.
You can shuffle by groups and flat the array. For example for:
Nodejs11:
let availableGroups = shuffleArray([groupAB, groupCD, groupEF, groupHG]);
let availablePositions = availableGroups.flat();
For lower versions:
let availableGroups = shuffleArray([groupAB, groupCD, groupEF, groupHG]);
availableGroups.forEach((v) => availablePositions.push(...v));

How to concat buffers with delimiter in node.js?

I'm trying to concat two buffers with a space in between them in Node.js.
Here is my code.
var buff1 = new Buffer("Jumping");
var buff2 = new Buffer("Japang");
var buffSpace = new Buffer(1);
buffSpace[0] = "32";
var newBuff = Buffer.concat([buff1, buffSpace, buff2], (buff1.length + buff2.length + buffSpace.length));
console.log(newBuff.toString());
As per official doc, the first argument will be the Array list of Buffer objects. Hence I've created buffSpace for space.
Class Method: Buffer.concat(list[, totalLength])
list : Array List of Buffer objects to concat
totalLength: Number Total length of the buffers when concatenated
I'm getting the result as expected but not sure whether it is right way to do so. Please suggest if any better solution to achieve the same.
There are three changes I would suggest.
First, if you are using Node v6, use Buffer.from() instead of new Buffer(), as the latter is deprecated.
Second, you don't need to pass an argument for totalLength to Buffer.concat(), since it will be calculated automatically from the length of all of the buffers passed. While the docs note it will be faster to pass a total length, this will really only be true if you pass a constant value. What you are doing above is computing the length and then passing that, which is what the concat() function will do internally anyway.
Finally, I would recommend putting this in a function that works like Array.prototype.join(), but for buffers.
function joinBuffers(buffers, delimiter = ' ') {
let d = Buffer.from(delimiter);
return buffers.reduce((prev, b) => Buffer.concat([prev, d, b]));
}
And you can use it like this:
let buf1 = Buffer.from('Foo');
let buf2 = Buffer.from('Bar');
let buf3 = Buffer.from('Baz');
let joined = joinBuffers([buf1, buf2, buf3]);
console.log(joined.toString()); // Foo Bar Baz
Or set a custom delimiter like this:
let joined2 = joinBuffers([buf1, buf2, buf3], ' and ');
console.log(joined2.toString()); // Foo and Bar and Baz
Read the Buffer stream and save it to file as:
const data = [];
req.on('data', stream => {
data.push(stream);
});
req.on('close', () => {
const parsedData = Buffer.concat(data).toString('utf8');
fs.writeFileSync('./test.text', parsedData);
});

Categories

Resources