I'm pretty new to learning to code. So i might get a lot of basics wrong.
Basically i am downloading API content from two different accounts via request-promise and want to merge them into a bigger array. I'm struggling with escaping my local data from the request-promise function and also combining it with the second array
Here's what i got so far:
//request the site and do some stuff with the data
rp(rpOptions)
.then(function (parsedBody) {
let incomingData1 = (parsedBody); //turning data into a value to change it a little
incomingData1.forEach((incomingData1) => {incomingData1.yearsRetired = 0}); //to add a new property
incomingData1 = JSON.stringify(parsedBody, ["favFood", "age", "work", "yearsRetired"], 2); //to filter only relevant properties into a JSON thing (i eventually want to save it to a txt file)
});
i'd then do the same for the second account and then try to get that data outside of the function and merge it into a single array so that it looks like this:
{
"first_account_name": {
"individual1": {
"favFood": 'fries',
"age": 23,
"work": 'astronaut'
"yearsRetired": 0
},
"individual2": {
"favFood": 'banana',
"age": 55,
"work": 'zookeeper'
"yearsRetired": 0
{
...
}
},
"second_account_name": { ... }
"individual6": {
"favFood": 'apple',
"age": 49,
"work": 'dinosaur'
"yearsRetired": 0
"individual7": {
"favFood": 'sausage',
"age": 33,
"work": 'doctor'
"yearsRetired": 0
{
...
}
how do i get my data into a variable outside of rp? and how do i set it up so that it ends up like a nested array?
Thanks a lot and sorry for being confusing :P
What you are looking for is a global array that gets data pushed into it on every Promise request called right. So firstly, create a simple array and place it on top of the page or if you are using a class just insert it into the respective fields.
Let accountDetails = [];
Next, inside then function call this variable like so,
rp(rpOptions)
.then(function (parsedBody) {
let incomingData1 = (parsedBody);
incomingData1.forEach((incomingData1) => {incomingData1.yearsRetired = 0});
incomingData1 = JSON.stringify(parsedBody, ["favFood", "age", "work", "yearsRetired"], 2);
accountDetails.push({
"individual1" : incomingData1
})
});
If you're using ES6
const processData = (data) => {
return data.map((item) => ({
favFood: item.favFood,
age: item.age,
work: item.work,
yearsRetired: 0
}))
}
// any value returned by then will be wrapped in promise
// and can be `await` ed
// you can also use
// const [ data1, data2 ] = await Promise.all([
// rp(requestOption1).then(data => processData(data)),
// rp(requestOption2).then(data => processData(data))
// ])
// if you want it to be executed parallely
const data1 = await rp(requestOption1).then(data => processData(data));
const data2 = await rp(requestOption2).then(data => processData(data));
const mergedData = [
...data1,
...data2
];
If you don't have async await
const processData = (data) => {
return data.map((item) => ({
favFood: item.favFood,
age: item.age,
work: item.work,
yearsRetired: 0
}))
}
Promise.all(
rp(requestOption1).then(data => processData(data)),
rp(requestOption2).then(data => processData(data))
).then(results => {
const mergedData = results.reduce((collection, result) => {
return collection.concat(result);
}, []);
})
Note:
I wrote the function name processData because I don't know what is being processed. I suggest you to be more specific on the function name. (e.g. what it does)
Related
I need to make a list of objects based on combined data from 2 arrays, one comes from a localStorage and the second one from Django backend. First of all objects from localStorage are displayed by showCart() function
export const showCart = () => {
if (typeof window !== undefined) {
if (localStorage.getItem("cart")) {
return JSON.parse(localStorage.getItem("cart"));
};
};
};
it returns data in this format: FE: { id: 1, amount: 7, size: "L", product: 1 }. product is the Foreign Key needed to match data from other array.
The second array comes form a backend and it is feched by getAllProducts() function
export const getAllProducts = () => {
return fetch(`${url}/products/`, {method: "GET"})
.then((response) => {
return response.json();
})
.catch((error) => console.log(error))
};
It returns data in this format: FE { name: "Red", id: 3, price: 33, image:"some-url"}
Now I need to create another list of objects by merging then by product of an object in first array with id of an object from the second one. The objects in the third array need to contain amount and size from first array as well as name, price and image from the second one. In the end I want to store it in useState().
This is what I came up with, I guess my code stops working arter first for loop:
const [cart, setCart] = useState([]);
const CheckAnonymousCart = () => {
getAllProducts()
.then((data) => {
const localCart = showCart();
var products = [];
for (let i = 0; i < localCart.lenght; i++) {
for (let y = 0; y < data.lenght; y++) {
if (localCart[i].product === data[y].id) {
console.log(localCart[i].product, data[y].id)
const item = {
name: data[y].name,
price: data[y].price,
image: data[y].image,
amount: localCart[i].amount,
size: localCart[i].size,
}
products.push(item)
break;
}
}
}
setCart(products);
})
.catch((error) => console.log(error))
};
Any thoughts?
In addition to Jacob's comment, you probably want to avoid FETCH'ing all products from the DB, because it requires more DB resources, most of the info is not required, and it makes the for-loop take longer to JOIN both lists.
Ideally, you would use a parameterized query like so:
return fetch(`${url}/products/?id=1&id=2&id=3`, {method: "GET"})
Where ?id=1&id=2&id=3 are a subset of the product IDs that you're retrieving.
Note: You will also want to sanitize/validate the product IDs in localStorage, because the data can be modified by the end-user, which is a potential attack vector by malicious users.
The problem could simply be the typo from the for loop conditions, but you can also accomplish this more succinctly using the JS ES6 methods:
const products = localCart.map(item => {
const match = data.find(x => x.id === item.product);
return {
amount,
size,
name: match?.name,
price: match?.price,
image: match?.image
}
});
So I've got this part of a code where I'm creating response for my project. Now I've managed to create data, but I've got response that I need to changes.
First here is my code:
exports.getById = (req, res) => {
const id = req.params.a_id;
articleService
.getById(id)
.then((article) => {
bankService
.getRates()
.then((list) => {
let prr = article.price;
let price = parseFloat(prr.replace(/\.| ?€$/g, '').replace(',', '.'));
let mjeseci = req.body.months;
let ratanks = list.map((rata) =>
LoanJS.Loan(price, !mjeseci ? 60 : mjeseci, rata.NKS)
);
const kreditNKS = ratanks.map((index) => index.sum);
const rataNKS = ratanks.map(
(index) => index.installments[0].installment
);
let eks = list.map((stopa) => stopa.EKS);
let name = list.map((ime) => ime.bank.name);
let nks = list.map((stopa) => stopa.NKS);
let type = list.map((ime) => ime.interest_type.name);
res.status(200).json({
kredit: {
kreditNKS: kreditNKS,
rataNKS: rataNKS,
stopaEKS: eks,
stopaNKS: nks,
tip: type,
ime: name,
}
})
.catch((err) => {
res.status(500).send('Error 1 ->' + err);
});
})
.catch((err) => {
res.status(500).send('Error ->' + err);
});
};
Explain of what it does: So I'm fetching single article from my DB which has price inside it, then I'm getting data about loan also from DB. Now I'm using that data from DB, using .map function to get values one by one and calculating for that values my final loan(that is ratanks part). Now I'm also extracting some other data that I need present to the user on the frontend.
Now my problem: It's sending my res as an object with one object, who has key:value pairs and values are array of data inside it. But I want it to be an array with multiple objects.
My response in postman right now:
{
"kredit": {
"kreditNKS": [
118406.54,
118348.2,
119400.33,
118022.46,
118262.44,
118811.84
],
"rataNKS": [
19734.42,
19724.7,
19900.05,
19670.41,
19710.41,
19801.97
],
"stopaEKS": [
"6.24",
"5.65",
"8.26",
"3.13",
"4.03",
"5.68"
],
"stopaNKS": [
"4.11",
"3.94",
"7",
"2.99",
"3.69",
"5.29"
],
"tip": [
"Fiksna",
"Promjenjiva",
"Fiksna",
"Promjenjiva",
"Fiksna",
"Fiksna"
],
"ime": [
"ZiraatBank",
"ZiraatBank",
"UniCredit",
"Raiffeisen Bank",
"Raiffeisen Bank",
"ASA Banka"
]
}
}
Where I need it to be something like this:
[
{
"kreditNKS":118406.54,
"rataNKS": 19734.42,
"stopaEKS": "6.24",
"stopaNKS": "4.11",
"tip": "Fiksna",
"ime": "ZiraatBank"
},
{
"kreditNKS":118348.2,
"rataNKS": 19724.7,
"stopaEKS": "5.65",
"stopaNKS": "3.94",
"tip": "Promjenjiva",
"ime": "ZiraatBank"
},
{
"kreditNKS":119400.33,
"rataNKS": 19900,05,
"stopaEKS": "8.26",
"stopaNKS": "7",
"tip": "Fiksna",
"ime": "UniCredit"
}
etc.....
]
Is it possible to modify something like this?
Any tips are welcome!
Thanks!
it looks like you're mapping your list into 4 arrays and then putting them inside a single object, where each array is a property of the said object.
let eks = list.map((stopa) => stopa.EKS);
let name = list.map((ime) => ime.bank.name);
let nks = list.map((stopa) => stopa.NKS);
let type = list.map((ime) => ime.interest_type.name);
res.status(200).json({
kredit: {
kreditNKS: kreditNKS,
rataNKS: rataNKS,
stopaEKS: eks,
stopaNKS: nks,
tip: type,
ime: name,
}
})
The way someArray.map(eachThing => doSomethingWithThing(thing)) works is that you iterate the entire array "someArray" and execute a function for each thing inside of it.
This means that instead of doing LoanJS.Loan(price, !mjeseci ? 60 : mjeseci, rata.NKS) for all the items of the list and write that to a new array called "ratanks", you can write your own function for all the items of the list, and during the iteration of each item do something like const loan = LoanJS.Loan(price, !mjeseci ? 60 : mjeseci, eachItem.NKS).
This being said, you should be able to get the object you want by mapping your list into an array of objects like this
const mappedKredits = list.map((eachObject) => {
const computedLoan = LoanJS.Loan(price, !mjeseci ? 60 : mjeseci, eachObject.NKS);
const kreditNKS = computedLoan.sum;
const rataNKS = computedLoan.installments[0].installment;
return {
"kreditNKS": kreditNKS,
"rataNKS": rataNKS,
"stopaEKS": eachObject.EKS,
"stopaNKS": eachObject.NKS,
"tip": eachObject.interest_type.name,
"ime": eachObject.bank.name,
}
});
res.status(200).json(mappedKredits);
Btw, try to use more descriptive names for the variables, if they're in English it'll be even better, otherwise, it makes it a bit harder for folks like me to understand what the code is doing, thus making it harder to help you.
I am using eslint and getting this error.
Expected to return a value in arrow function
The error is showing on the third line of the code.
useEffect(() => {
let initialPrices = {};
data.map(({ category, options }) => {
initialPrices = {
...initialPrices,
[category]: options[0].price,
};
});
setSelectedPrice(initialPrices);
}, []);
The map function must return a value. If you want to create a new object based on an array you should use the reduce function instead.
const reducer = (accumulator, { category, options }) => (
{...accumulator, [category]:options[0].price}
)
const modifiedData = data.reduce(reducer)
More information https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
The map function is intended to be used when you want to apply some function over every element of the calling array. I think here it's better to use a forEach:
useEffect(() => {
let initialPrices = {};
data.forEach(({ category, options }) => {
initialPrices = {
...initialPrices,
[category]: options[0].price,
};
});
setSelectedPrice(initialPrices);
}, []);
Your map function should return something. Here it's not the case so the error happens. Maybe a reduce function will be more appropriate than map?
From what I can see in your case, is that you want to populate initialPrices, and after that to pass it setSelectedPrice. The map method is not a solution, for you in this case, because this method returns an array.
A safe bet in your case would a for in loop, a forEach, or a reduce function.
const data = [
{
category: "ball",
options: [
{
price: "120.45"
}
]
},
{
category: "t-shirt",
options: [
{
price: "12.45"
}
]
}
];
The forEach example:
let initialPrices = {};
// category and options are destructured from the first parameter of the method
data.forEach(({ category, options}) => {
initialPrices[category] = options[0].price;
});
// in this process I'm using the Clojure concept to add dynamically the properties
setSelectedPrice(initialPrices);
The reduce example:
const initialPrices = Object.values(data).reduce((accumulatorObj, { category, options}) => {
accumulatorObj[category] = options[0].price
return accumulatorObj;
}, {});
setSelectedPrice(initialPrices);
One data set is an object of arrays of ids and another is an object of arrays of ids and names. What I'd like to do is check if the ids from the first data exist in the second data set and if they do then display the names.
This is what is being called by the component, which works correctly:
<td>Genre</td>
<td>{this.matchGenres(this.props.movie.genre_ids, this.props.genres)}</td>
And this is the function that I can't get to work:
matchGenres = (genres, genreList) => {
genres.forEach((genre) => {
genreList.filter((list) => {
return list.id === genre;
}).map((newList) => {
return newList.name;
});
});
}
It looks like the operation performs correctly and returns the right names when I console.log it! But! its not showing up in the component on render.
const genres = [{
id: 1,
name: "Jazz Music"
}, {
id: 2,
name: "Something"
}];
const genreList = [1, 10, 100];
matchGenres = (genres, genreList) => genres
.filter(genre => genreList.includes(genre.id))
.map(genre => genre.name);
const matchedGenres = matchGenres(genres, genreList);
console.log(matchedGenres);
But! its not showing up in the component on render.
Its because your function doesn't return anything. You return inside filter and map and your function does not return anything. Also note that forEach always return undefined
You just need a minor change. Try this
let genres = ["1", "2", "3"];
let genreList = [{
id: "2",
name: "Two"
}, {
id: "32",
name: "Three"
}]
matchGenres = (genres, genreList) => {
return genreList.filter((list) => {
// findIndex return array index if found else return -1 if not found
return genres.findIndex(genere => genere === list.id) > -1;
}).map(list => list.name);
}
console.log(matchGenres(genres, genreList));
This is the solution that ended up working:
if (genreList.length !== 0) {
return genres.map(genre => genreList.find(list => list.id === genre)).map((newList) => newList.name) + ',';
}
For some reason the value of GenreList, which is an array, was showing up as empty for the first couple times the function is call. Thats another problem I'll have to look at but the if statement solves for it for the time being.
In my post request I need to pass an array with an object inside it.
when I tried to add new properties inside an object its adding.
but when I tried to add when an object is present inside an array its not adding.
I have sportsvalues as array const sportsValues = [{ ...values }];
I am trying to build something like this, so that I can pass in the api
[
{
"playerName": 3,
"playerHeight": 1
}
]
can you tell me how to fix it.
providing my code snippet below.
export function sports(values) {
const sportsValues = [{ ...values }];
sportsValues.push(playerName:'3');
console.log("sportsValues--->", sportsValues);
// sportsValues.playerName = 3//'';
// sportsValues.playerHeight = 1//'';
console.log("after addition sportsValues--->", sportsValues);
console.log("after deletion sportsValues--->", sportsValues);
return dispatch => {
axios
.post(`${url}/sport`, sportsValues)
.then(() => {
return;
})
.catch(error => {
alert(`Error\n${error}`);
});
};
}
Since sportsValues is an array of objects, you can push new object into it. Check out code below.
const sportsValues = [];
sportsValues.push({
playerName:'3',
playerHeight: 1,
});
console.log(sportsValues);
I don't fully understand what you're trying to do, but here's some pointers:
If you're trying to update the object that's inside the array, you first have to select the object inside the array, then update it's attribute:
sportsValues[0].playerName = 3
although, I recommend building the object correctly first, then passing it to the array, it makes it a little easier to understand in my opinion:
const sportsValues = [];
const firstValue = { ...values };
firstValue.playerName = '3';
sportsValues.push(firstValue);
or
const firstValue = { ...values };
firstValue.playerName = '3';
const sportsValues = [firstValue];
or
const sportsValues = [{
...values,
playername: '3',
}];
if you're trying to add a new object to the array, you can do this:
const sportsValues = [{ ...values }];
sportsValues.push({ playerName: '3' });
etc...
Array.push adds a new item to the array, so in your code, you're going to have 2 items because you assign 1 item at the beginning and then push a new item:
const ar = [];
// []
ar.push('item');
// ['item']
ar.push({ text: 'item 2' });
// ['item', { text: 'item 2' }]
etc...
export function sports(values) {
const sportsValues = [{ ...values }];
sportsValues.push(playerName:'3');
let playerName='3'
sportsValues.playerName= playerName; // you can bind in this way
console.log("sportsValues--->", sportsValues);
return dispatch => {
axios
.post(`${url}/sport`, sportsValues)
.then(() => {
return;
})
.catch(error => {
alert(`Error\n${error}`);
});
};
}