I want to replace the value of an object inside an array? - javascript

I have a timestamp in my array that I have removed the UTC letters from and I want to replace the old timestamp with the "new" timestamp(without UTC)
Maybe there is an even easier way to do the removing?
So I've tried to loop over my data with .forEach and .map trying to replace it but still haven't figure it out how to exactly do so.
I've watched a bunch of Stackoverflow threads about this but haven't found a solution that I get to work....clearly missing something or writing something wrong.
So can anyone guide me how to solve this in the best way?
const data = [
{
timestamp: "2019-03-01 09:00:00UTC",
url: "/blub.html",
userid: "12345"
},
{
timestamp: "2019-03-01 09:00:00UTC",
url: "/cont.html ",
userid: "12346"
},
{
timestamp: "2019-03-01 10:00:00UTC ",
url: "/cont.html ",
userid: "12345"
},
{
timestamp: "2019-03-01 10:30:00UTC",
url: "/ho.html ",
userid: "12347"
}
];
console.log("data", data);
console.log("ex: first data object:", data[0]);
//loop through and grab the timestamp in each object and remove the UTC stamp
const GrabTimeStamp = () => {
data.forEach(function (objects, index) {
const timeStamp = objects.timestamp;
const newTimeStamp = timeStamp.slice(0, 19);
console.log("newTimeStamp:", newTimeStamp, index);
//next step to replace the old timestamp with newTimeStamp
});
};
GrabTimeStamp()

Your code looks fine, just refactor that fragment (best approach to work with forEach):
data.forEach((item, index) => {
const timeStamp = item.timestamp;
const newTimeStamp = timeStamp.slice(0, 19);
item.timestamp = newTimeStamp;
});
and it should work.

Did you know that variables declared with "const" could not be changed? So it seems like you want to use "var" here. The last 3 letters can be removed by "slice(0, -3)".
var data = [
{
timestamp: "2019-03-01 09:00:00UTC",
url: "/blub.html",
userid: "12345"
},
{
timestamp: "2019-03-01 09:00:00UTC",
url: "/cont.html ",
userid: "12346"
},
{
timestamp: "2019-03-01 10:00:00UTC",
url: "/cont.html ",
userid: "12345"
},
{
timestamp: "2019-03-01 10:30:00UTC",
url: "/ho.html ",
userid: "12347"
}
];
console.log("data", data);
console.log("ex: first data object:", data[0]);
//loop through and grab the timestamp in each object and remove the UTC stamp
var grabTimeStamp = () => {
data.forEach(function (object, index) {
var newTimeStamp = object.timestamp.slice(0, -3);
console.log("newTimeStamp:", newTimeStamp, index);
//next step to replace the old timestamp with newTimeStamp
object.timestamp = newTimeStamp;
});
};
grabTimeStamp();
Since it does seem like you are fairly new to coding, I tried to change only a few things in your code. However your function grabTimeStamp can be done shorter:
function removeTimestamp(data){
data.foreach((item, index) => {
item.timestamp = item.timestamp.slice(0, -3);
});
}
removeTimestamp(data);

Related

Instant filter function with multiple filters

I would like to build a search function with several different filters. I have a RangeSlider component and function that give me the respective min max values. I save these filter values as objects and send them to the backend immediately each time a filter is changed.
Here I work with if, else conditions, which is certainly not the right way, but I didn't know what else to do and wanted to have at least a working prototype.
If you have one or two filters, this can still work, but not if you have many different ones. Furthermore, I wonder how to optimise the whole filtering process? With every request, the entire collection is searched. It would be great if the previous search query is applied to each new filter instead of searching through the entire collection again.
How can this be achieved?
Frontend
Every time a filter is updated activeFilters will be sent to the backend
const activeFilters = reactive({ salePrice: '', space: '' })
async function updateFilter(minmax, property) {
activeFilters[property] = minmax
const filteredObjects = await $fetch('/api/properties/filtered', {
method: 'POST',
body: activeFilters,
})
return filteredObjects
}
Backend
body = { "salePrice": { "min": 630000, "max": 850948 }, "space": { "min": 53, "max": 167 } }
export default defineEventHandler(async (event) => {
const body = await readBody(event)
try {
if (body.salePrice !== '' && body.space !== '') {
const properties = await Property.find({
salePrice: { $gte: body.salePrice.min, $lte: body.salePrice.max },
livableSurface: { $gte: body.space.min, $lte: body.space.max },
})
return properties
}
if (body.salePrice !== '') {
const properties = await Property.find({
salePrice: { $gte: body.salePrice.min, $lte: body.salePrice.max },
})
return properties
}
if (body.space !== '') {
const properties = await Property.find({
livableSurface: { $gte: body.space.min, $lte: body.space.max },
})
return properties
}
const properties = await Property.find()
return properties
} catch (err) {
console.dir(err)
event.res.statusCode = 500
return {
code: 'ERROR',
message: 'Something went wrong.',
}
}
})
Html
<InputsRangeSlider
:config="salePriceSliderConfig"
#updated-min-max="updateFilter($event, 'salePrice')"
/>
<InputsRangeSlider
:config="spaceSliderConfig"
#updated-min-max="updateFilter($event, 'space')"
/>
Maybe something like this?
const {salePrice, space} = body;
const conditions = {};
if (salePrice) conditions.salePrice = {$gte: salePrice.min, $lte: salePrice.max};
if (space) conditions.livableSurface = {$gte: space.min, $lte: space.max};
return Property.find(conditions);

JavaScript, fetch, API

i want to do the following: get a random name with fetch from this website https://swapi.dev/api/people/, which i did and i can see it in my html page then i want also to get a random planet, here i need to access the homeworld key, and to return the link, before returning the link i formatted to get a random url and from this one i also have to show the name of the planet on my page. The first fetch works fine, at least i think but the 3rd .then() is not working or at least i don't know how to access the information from the homeworld url. This is my first time trying fetch() and it will be nice if you guys can help me telling where i did wrong in code and maybe different solutions but not so complicated :D tnks
let randomNumber = Math.floor(Math.random()*9)
const fetchPromise = fetch("https://swapi.dev/api/people/");
let test
let test2
let planets = document.querySelector('#age')
fetchPromise
.then((response) => {
if (!response.ok) {
throw new Error(`Http error: ${response.status}`);
}
return response.json();
})
.then((json) => {
console.log(json.results[randomNumber].name)
showRandomUserData(json)
test = json.results[0].homeworld
test = test.slice(0, -2)
// console.log(test + randomNumber + "/");
// console.log(test + "/" + randomNumber + "/");
test = test + randomNumber + "/";
return fetch(test)
// return fetch("https://swapi.dev/api/planets/2/");
})
.then(response => response.json()).then(json =>
{ test2=json.name
console.log(test2);
planets.innerHTML = test2
})
showRandomUserData = (randomUser) => {
document.querySelector("#name").innerHTML =
randomUser.results[randomNumber].name;
}
Solved
Here's a simple solution that uses fetch() to grab data from both those URLs and then insert all the people and the one planet that is returned into your web page:
function myFetch(...args) {
return fetch(...args).then(response => {
if (!response.ok) {
throw new Error(`fetch failed with status ${response.status}`);
}
return response.json();
});
}
Promise.all([
myFetch("https://swapi.dev/api/people/"),
myFetch("https://swapi.dev/api/planets/2/")
]).then(([people, planet]) => {
const peopleDiv = document.getElementById("people");
let peopleHTML = "";
for (let p of people.results) {
peopleHTML += `<div>${p.name}</div>`;
}
peopleDiv.innerHTML = peopleHTML;
const planetDiv = document.getElementById("planets");
let planetHTML = `<div>${planet.name}</div>`;
planetDiv.innerHTML = planetHTML;
}).catch(err => {
console.log(err);
});
<div id="people"></div>
<hr>
<div id="planets"></div>
As for using the results, the people URL returns a structure that looks like this:
{
count: 82,
next: 'https://swapi.dev/api/people/?page=2',
previous: null,
results: [
{
name: 'Luke Skywalker',
height: '172',
mass: '77',
hair_color: 'blond',
skin_color: 'fair',
eye_color: 'blue',
birth_year: '19BBY',
gender: 'male',
homeworld: 'https://swapi.dev/api/planets/1/',
films: [Array],
species: [],
vehicles: [Array],
starships: [Array],
created: '2014-12-09T13:50:51.644000Z',
edited: '2014-12-20T21:17:56.891000Z',
url: 'https://swapi.dev/api/people/1/'
},
{
name: 'C-3PO',
height: '167',
mass: '75',
hair_color: 'n/a',
skin_color: 'gold',
eye_color: 'yellow',
birth_year: '112BBY',
gender: 'n/a',
homeworld: 'https://swapi.dev/api/planets/1/',
films: [Array],
species: [Array],
vehicles: [],
starships: [],
created: '2014-12-10T15:10:51.357000Z',
edited: '2014-12-20T21:17:50.309000Z',
url: 'https://swapi.dev/api/people/2/'
}
}
So, you have people.results which is an array and you can access people.results[n] to get an item from that array. That item will be an object which has properties like .name, .height, etc...
The specific planet URL you show returns a single planet object like this:
{
name: 'Alderaan',
rotation_period: '24',
orbital_period: '364',
diameter: '12500',
climate: 'temperate',
gravity: '1 standard',
terrain: 'grasslands, mountains',
surface_water: '40',
population: '2000000000',
residents: [
'https://swapi.dev/api/people/5/',
'https://swapi.dev/api/people/68/',
'https://swapi.dev/api/people/81/'
],
films: [
'https://swapi.dev/api/films/1/',
'https://swapi.dev/api/films/6/'
],
created: '2014-12-10T11:35:48.479000Z',
edited: '2014-12-20T20:58:18.420000Z',
url: 'https://swapi.dev/api/planets/2/'
}
So, you access properties on that object as in planet.name.
Notice that the people results are paged. There are 82 total results, but only 10 come in this first result. The rest come with results for other pages such as https://swapi.dev/api/people/?page=2.
Similar to this answer but using async/await to avoid callback hell. If you can, try using this approach. Why?
Excellent recommendation in that answer by jfriend00 to use Promise.all instead of separate fetch calls, as that enables fetching to happen in parallel. To know more.
sandbox to test and try
const fetchData = async (...args) => {
try {
const response = await fetch(...args);
return response.json();
} catch (err) {
throw new Error(`fetch failed with status ${err?.message}`);
}
};
const updateDOM = (people, planet) => {
document.getElementById("people").innerHTML =
people.results.reduce((s, p) => s + `<div>${p.name}</div>`, "");
document.getElementById("planets").innerHTML = `<div>${planet.name}</div>`;
};
const populateData = async () => {
try {
const [people, planet] = await Promise.all([
fetchData("https://swapi.dev/api/people/"),
fetchData("https://swapi.dev/api/planets/2/"),
]);
// do stuff with 'people' or 'planet'
// example, get
// const firstPersonsHomeworld = people.results[0].homeworld;
// console.log(firstPersonsHomeworld);
// or
// const planetName = planet.name;
// console.log(planetName);
updateDOM(people, planet);
} catch (err) {
// errorHandler(err);
console.error(err);
}
};
// start app
populateData();

I can't replace the value of an array returned by mongoose

I have a notifications.find query (mongoose) that returns multiple sheets
Notification.find({id: id}, function(err, notifications){}
I need to convert the timestamp values that are returned like that
[
{
_id: new ObjectId("12934193c51a231b0165425a"),
userid: '62921df1c14a2eea0efa9399',
timestamp: 1653817696599,
},
{
_id: new ObjectId("11934193c51a231b0165425a"),
userid: '62921df1c14a2eea0efa9399',
timestamp: 1653817696600,
}
]
I tried this
notifications.forEach((element, index) => {
notifications[index].timestamp = new Date(notifications[index].timestamp);
});
and this code
new Date(notifications[index].timestamp);
seems to work by converting the timestamp of each value, but I can't replace it in the array
I've been on this issue for several hours
Instead of forEach use map
const newNotifications = notifications.map((element, index) => {
return {
...element,
timestamp: new Date(element.timestamp),
}
});

How to check in array if it contains given element

I am trying below code but its not working so first am trying to get a person department Name currently, hard coded it to check
var arr=[]
let CurrDept = "AB-CDE-F";
var Detept=CurrDept.substring(0,5);
arr.push(Detept)
Now in below line of code i am trying this line so it should exclude all results which start from AB-CD
var Userprofiledept=data.value[0].UserId.Department;
const isInArray = arr.indexOf(Userprofiledept) > -1;
isInArray should be false which can be put in my condition but it always give true
Can anyone help ?
So current user department may be AB-CDE-F and data i am getting from my rest call may have lots of department for many users AB-CDE-F,AB-CDE-F,AB-CDE,AB-CD,AB-C
so only want to exclude results which are AB-CDE-F,AB-CDE-F,AB-CDE,AB-CD as they are starting with AB-CD
You can use Array.prototype.filter and String.prototype.startsWith.
const
data = {value: [{ UserId: { ID: 14, Email: "sdfds", Department: "AB-CD-EF" } }, { UserId: { ID: 14, Email: "sdfds", Department: "AB-CD" } }, { UserId: { ID: 14, Email: "sdfds", Department: "AB-C" } }]},
discard = "AB-CD",
res = data.value.filter((v) => !v.UserId.Department.startsWith(discard));
console.log(res);
You could move the functionality into a function and check if the substring exists and add, if necessary.
const
add = string => {
string = string.slice(0, 5);
if (array.includes(string)) return;
array.push(string);
}
array = [];
add('AB-CDE-F');
console.log(array);
add('AB-CDE-F');
console.log(array);
add('AB-CDE');
console.log(array);

Merging two arrays from chained axios requests

I am chaining a bunch of axios get request to different endpoints of an API and I'm trying to create an array like this from the data (simplified):
[
{
name: "John",
id: 1,
gender: "male"
},
{
name: "Anna",
id: 2,
gender: "female"
},
]
In one of the requests I retrieve each person's name and id in an array like this:
[
{
name: "John",
id: 1
},
{
name: "Anna",
id: 2
},
]
Now I only need to get their gender by sending each persons's id in two separate requests to an endpoint.
I have spent hours trying to construct the array at the top with push() and then() but I just can't get it right.
How do I go about this?
I'm chaining the axios requests like this btw:
axios.get('api/' + endpoint1]).then(response => {
axios.get('api/' + endpoint2).then(response => {
axios.get('api/' + endpoint3).then(response => {
// and so on...
});
});
});
UPDATE 1:
I feel like I didn't explain the problem properly. This is what my code looks like right now, starting from the last promise. How can I change it in order to get the array at the top of my question?
.then(response => {
people= response.data; // Array of people including their name id (not their gender though)
for (var key in people) {
var person = {};
person["name"] = people[key].node.name;
person["id"] = people[key].node.id;
finalArray.push(person);
axios.get('api/' + endpoint3, { // Endpoint for getting a persons gender from id
params: {
personId: person.id
}
}).then(response => {
// I don't know what to do here...
});
}
console.log(finalArray); // Gives me an array of objects without "gender".
});
UPDATE 2:
Thanks alot for your answers!
I've combined some of your solutions and this is how my real code looks right now. The requests to http://api.ntjp.se/coop/api/v1/serviceProducers.json are not sent. Why?
I also don't want to keep the whole objects within the cooperations response array before calling http://api.ntjp.se/coop/api/v1/serviceProducers.json. I just want to save two specific key/value pairs from each object. These two key/value pairs are both within an object called "serviceContract" within in each response object. How do I save them?
<html>
<head>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
getConnectionStatusData();
async function getConnectionStatusData() {
let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
params: {
namespace: "crm:scheduling"
}
});
serviceDomainId = serviceDomains.data[0].id;
let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
params: {
platform: "NTJP",
environment: "PROD"
}
});
connectionPointId = connectionPoints.data[0].id;
let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
params: {
logicalAdress: "SE2321000016-167N",
serviceConsumerHSAId: "SE2321000016-92V4",
connectionPointId: connectionPointId
}
});
logicalAddressId = logicalAddresss.data[0].id;
let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId
}
});
consumer = serviceConsumers.data.filter(obj => {
return obj.hsaId === "SE2321000016-92V4"
});
serviceConsumerId = consumer[0].id;
let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
include: "serviceContract"
}
});
for(var idx in cooperations.data) {
var data = async () => { return await axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
serviceContractId: cooperations.data[idx].serviceContract.id
}
}) }
cooperations.data[idx].producerDescription = data.description;
cooperations.data[idx].producerHSAId = data.hsaId;
}
console.log(cooperations.data);
}
</script>
</body>
UPDATE 3
I finally made it work but why do I have to reference to the data like response.data[0].description when I push it into finalResult in the end? I mean, why doesn't just response.data.description work, as it does for #Cold Cerberus?
Other than that, is my code ok in or have I done something wrong?
Thanks guys!
<html>
<head>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
getConnectionStatusData();
async function getConnectionStatusData() {
let serviceDomains = await axios.get('http://api.ntjp.se/coop/api/v1/serviceDomains.json', {
params: {
namespace: "crm:scheduling"
}
});
serviceDomainId = serviceDomains.data[0].id;
let connectionPoints = await axios.get('http://api.ntjp.se/coop/api/v1/connectionPoints.json', {
params: {
platform: "NTJP",
environment: "PROD"
}
});
connectionPointId = connectionPoints.data[0].id;
let logicalAddresss = await axios.get('http://api.ntjp.se/coop/api/v1/logicalAddresss.json', {
params: {
logicalAdress: "SE2321000016-167N",
serviceConsumerHSAId: "SE2321000016-92V4",
connectionPointId: connectionPointId
}
});
logicalAddressId = logicalAddresss.data[0].id;
let serviceConsumers = await axios.get('http://api.ntjp.se/coop/api/v1/serviceConsumers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId
}
});
consumer = serviceConsumers.data.filter(obj => {
return obj.hsaId === "SE2321000016-92V4"
});
serviceConsumerId = consumer[0].id;
let cooperations = await axios.get('http://api.ntjp.se/coop/api/v1/cooperations.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
include: "serviceContract"
}
});
var finalData = [];
cooperations.data.forEach(function(cooperation) {
axios.get('http://api.ntjp.se/coop/api/v1/serviceProducers.json', {
params: {
connectionPointId: connectionPointId,
logicalAddressId: logicalAddressId,
serviceDomainId: serviceDomainId,
serviceConsumerId: serviceConsumerId,
serviceContractId: cooperation.serviceContract.id
}
}).then(response => {
finalData.push({serviceContract: cooperation.serviceContract.namespace, serviceProducerDescription: response.data[0].description, serviceProducerHSAId: response.data[0].hsaId});
});
});
console.log(finalData);
}
</script>
</body>
I'm not quite sure of your specific problem. But assuming that what you mean is you have two endpoints, first is the one that returns an array of object (lets call it 'getPeopleArray'):
[
{
name: "John",
id: 1
},
{
name: "Anna",
id: 2
}
]
and second endpoint returns the gender of the given id (lets call it 'getGender' with one param id), .push will not do the job for you.
Your problem can be solved with something like this:
let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
peopleArray = people;
people.forEach((person, index) => {
axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
.then(gender => {
peopleArray[index].gender = gender;
});
});
});
First is you save the returned array of your first request and then you will have to loop through each object in that array to get and assign their genders from your second endpoint using the index argument of your [].forEach(callbackfn). As long as there is no manipulation with peopleArray during or before all requests are finished, the index will be correct.
Update 2:
In response to your question in the comments "why .push doesn't work?", I decided to make another approach If you want to end your algorithm with using .push and go without tracking indexes.
let peopleArray = [];
axios.get('api/' + 'getPeopleArray').then(people => {
people.forEach((person) => {
axios.get('api/' + 'getGender?id='.concat(person.id.toString()))
.then(gender => {
peopleArray.push({id: person.id, name: person.name, gender, gender});
});
});
});
This way you will only push your object to your collection peopleArray when its respective gender is also fetched. This will also eliminate having to use .map (as suggested in the comments) for storing only the individual object's properties you desire to keep since you pushed a new structured object on line peopleArray.push({id: person.id, name: person.name, gender, gender});.
I do not like to read chained promises and prefer to use async/await instead. You could get your list first and then loop through that list with a map and request the gender for each name. Remember that you have to wait for all promises to resolve inside your map before you can proceed.
const axios = require('axios');
async function getPeople() {
let firstResult = await axios.get('api/path/endpoint1');
// firstResult = [{name: "John", id: 1}, {name: "Anna", id: 2}]
let updatedResult = firstResult.map(async item => {
let people = await axios.get('api/path/endpoint2' + item.name); // or however your endpoint is designed
// people = {name: "John", id: 1, gender: male}
item.gender = people.gender;
return item;
});
// updatedResult = undefined
Promise.all(updatedResult)
.then(finalResult => console.log(finalResult));
// [{name: "John", id: 1, gender: male}, {name: "Anna", id: 2, gender: female}]
}
You can use async/awaits and reassign gender key to first endpoint data ...
var users;
axios.get('api/' + endpoint1]).then(response => {
users = response; // assume all user id list
for(var idx in users) {
var data = async () => { return await axios.get('api/' + users[idx].id) } //get gender api by user id
users[idx].gender = data.gender; //create gender key value
}
console.log(users);
});

Categories