This question already has answers here:
Why is using "for...in" for array iteration a bad idea?
(28 answers)
Closed 6 years ago.
So I've been trying to figure out what exactly I'm missing in a logic loop I've created. The following example closely recreates my situation:
async function x() {
const items = await Items.find().exec();
console.log(items);
for(item in items) {
console.log(item);
}
}
So the outcome for that little code block for me is that items holds an array of mongoose documents as expected, but here is the issue: item apparently is 0.
When I look at the mongoose document the only value that is 0 on it is the __v value, which in my understanding is the version that document is at. Am I just missing something or is this just not possible?
To note this returns as expected:
async function x() {
const items = await Items.find().exec();
console.log(items);
items.forEach(item => {
console.log(item);
});
}
This logs both the array and a single mongoose document, the issue is I'm looking to do another async call in that second loop that I want to await so if that's not possible I'll have to break it up more I guess, but I'd like ot know where that 0 is coming from if possible.
EDIT: To clarify, I have tried running toObject on both but it doesn't seem to change anything, and actually on the array it says toObject isn't a function of the array.
EDIT 2: I was not asking why for...in was bad, I was asking why it was not iterating over the "array" I had, it was due to the fact that mongoose returns a collection and for...in iterates over the enumerable properties of an object.
iterating over an array using
for(item in ['a', 'b']) {
console.log(item)
}
will give you the array indexes: 0, 1
You are looking for
for(const item of ['a', 'b']) {
console.log(item)
}
And that will print values: a, b
Check this
Related
Apologies for the poorly worded title, I'm not sure how to phrase the question. I have made a quiz app in React which allows the user to choose the number of questions and for each question, there are five possible answers they can toggle between.
Because of the toggle feature, if they toggle between the possible answers, I need to be able to add the new array and replace the old corresponding one, which will then be checked to see if they are correct when they check the score. I've tried for hours to figure this out but I just can't. I've come sort of close but it only works if the user doesn't toggle between the answers.
Here's my code so far and the only semi-workable solution that I've come up with but is ugly and only works if the user doesn't toggle between answers for the same question.
function getDataFromQuestionComponent(dataFromComponent){
getQuizData.push(dataFromComponent)
// stop the score data array from growing continously
if (getQuizData.length > amount) {
maintainScoreArrayLength(getQuizData)
}
}
function maintainScoreArrayLength(quizDataArray){
// to find if which answers are matching so the original can be replaced
// with the new answer (too obscure - find a better solution)
let lastItemZeroIndexText = (quizDataArray[quizDataArray.length - 1][0].body)
for (let i=0; i<quizDataArray.length; i++) {
if (lastItemZeroIndexText === getQuizData[i][0].body) {
newArray.push(getQuizData.indexOf(getQuizData[i]))
}
}
// remove the previous item from the array
getQuizData.splice(newArray[0], 1)
}
This is what the array of object arrays looks like in the console:
The .map array method and array destructuring make it possible to do this more cleanly.
I can't quite tell how you are storing the data for the quiz questions/answers, but here's an example of how you could do it if you are saving all of the quiz data in a state object and storing the index of the current question:
const [quizData, setQuizData] = useState(initialQuizData);
const [currentQuestion, setCurrentQuestion] = useState(0);
const onSelectAnswer = (selectedAnswer) => {
// create an object with updated data for the current question
const updatedQuestionData = {
...quizData[currentQuestion],
multipleChoiceAnswers: quizData[
currentQuestion
].multipleChoiceAnswers.map((answerOption) => ({
...answerOption,
selected: selectedAnswer === answerOption.body
}))
};
// iterate through the questions
// and save either the
// updatedQuestionData or the prevState data
// (store the updatedQuestionData over the prevState data for that question)
setQuizData((prevState) => [
...prevState.map((question, index) =>
currentQuestion === index ? updatedQuestionData : question
)
]);
};
To break it down, we create a copy of the answers array but we set selected to false unless it is the answer the user just clicked:
multipleChoiceAnswers.map(answerOption) => ({
...answerOption,
selected: selectedAnswer === answerOption.body
})
The updated question object is made by copying the data from the current question, then overriding the array of answers with the updated copy of the answers we just made in the code snippet above. That is what is happening in this part:
const updatedQuestionData = {
...quizData[currentQuestion],
multipleChoiceAnswers: // The updated answers array
};
Here's a full example on code sandbox:
So I have a db document that holds some string values in an array, I want to push just the array from every entry into an array in the application for usage later, But I can see the array fine on the fetch, and when I iterate it but my "Global array" is staying empty can someone explain why?
specialDates : Specialdates[] = [];
specialRange: any[] = [];
this.specialDates.forEach(ag => {
//ag,range -> I can see fine
this.specialRange.push(ag.range);
//this.specialrange -> Stays empty
});
Array looks something like the following:
1205,1206,1207,1208
What is wrong with this approach?
Reason for doing this is because the documents have 2 fields minimum: EG ->
ID/Array
And I just need the array
this.specialRange = this.specialDates.map(ag => ag.range)
I have Java service which retrieves table from oracle database and I want to display the result in Angular application, also I have an array of Objects in Angular:
resultSet:Info[]=[];
service:
pastHourInfo() {
const url='/SearchApp-1.0/users/transaction';
return this.http.get(url).pipe(map((data:any)=>data));
}
this is my service subscribtion:
checkPasHourInfo() {
this.searchService.pastHourInfo().subscribe(data => {
console.log("we got: ",data);
this.resultSet.push(data);
console.log(this.resultSet.length);
},
error => {
console.log("Error",error);
},);
Problem is the next. The result is 77 rows .
console.log("we got: ",data) gives correct result. you cans see it here
but console.log(this.resultSet.length); prints "1" when it must be 77.
What is the problem?
From your screenshot it seems that your are pushing the array into your result array, you could spread your data into the array as such:
this.resultSet.push(...data);
You are pushing an array into an array. So your array looks like this
resultSet[].length = 1;
resultSet[0].length = 77;
Instead of doing:
this.resultSet.push(data);
try this:
this.resultSet.concat(data);
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
You can add array into another array as below:
this.resultSet.concat(data)
This question does it in Javascript, but I would have thought in Typescript I could do some kind of map/filter operation to do the same thing.
I have an array of objects called Room. Each Room has a property called Width (which is actually a string, eg '4m', '5m', '6.5m').
I need to check the entire array to see if all the widths are the same.
Based on that question I have this, but I was wondering if TypeScript has something better:
let areWidthsTheSame = true;
this.qp.rooms.forEach(function(room, index, rooms) {
if (rooms[index] != rooms[index+1]) areWidthsTheSame = false;
});
Any ideas?
FYI the linked question has a comment that links to these performance tests, which are interesting in the context of this question:
This can be done in the following way:
const widthArr = rooms.map(r => r.width);
const isSameWidth = widthArr.length === 0 ? true :
widthArr.every(val => val === widthArr[0]);
We first convert the rooms array to an array of widths and then we check if all values in widths arrays are equal.
This question already has answers here:
Mongoose validation error but I put documents correctly
(2 answers)
Closed 6 years ago.
I have this variable that I needed to fill up using request body
var orderItem = {
userPurchased: body.userPurchased,
products:[{
product: body.products.product,
size: body.products.size,
quantity: body.products.quantity,
subTotal: body.products.subTotal
}],
totalQuantity: body.totalQuantity,
totalPrice: body.totalPrice,
otherShipAd: body.otherShipAd,
modeOfPayment: body.modeOfPayment
};
Here is my request body looks like.
The problem here is that the request body is an array of objects and if I access it in the way I shown on top, it would be undefined. If I put the number of the array like body.products.product[0], all the records will be the same.
Can anyone tell me how to iterate all the products and put it inside the variable?
Not sure if I've understood what your dilemma is but from the fact that your destination object appears to have the exact same schema as your source, why don't you just assign that value to your var?
var orderItem = request.body;
Let's say you still had some reason to need to create that copy of the array from request.body? This would still be just a one-liner to assign the request.body array to your target variable:
var orderItem = {
userPurchased: body.userPurchased,
products: body.products,
totalQuantity: body.totalQuantity,
totalPrice: body.totalPrice,
otherShipAd: body.otherShipAd,
modeOfPayment: body.modeOfPayment
};
according to your console response
you should use:
var product;
for(var i=0; i< body.products.length;i++)
{ product = [];
product[product] =body.products[i].product[0];
// set all properties
}
orderItem.products.push(product);