I am using mongodb and am building an application with two collections: users and items.
I'd like for users to be able to save items that they like and go to their saved items page where the items would be displayed in the reverse order that they were saved (last saved appears first).
At the moment, I am adding every saved item's id along with the savedDate to the user's profile savedItems array like so:
user profile
{
savedItems: [{id: "", savedDate: ""}, {id: "", savedDate: ""}, etc...]
}
Whenever I need to retrieve those items, I query the items collection for objects with ids $in this array. Like this:
var items = Items.find({_id: {$in: _.pluck(user.savedItems, 'id')}});
The problem here is that I can't order those items according to the addedDate.
So is it possible to map the addedDate onto every object of the retrieved items?
(Something like: if retrievedItems.id == savedItems.id, then push the addedDate there.)
Which would result in an items array like this:
[
{id:"", itemName:"", price: "", [...], savedDate: ""},
{id:"", itemName:"", price: "", [...], savedDate: ""},
[...]
]
Thank you.
JSFIDDLE
I created two function to help you do it:
function mergeDates(listDates, listItems) {
for (var i = 0; i < listDates.length; i++) {
var index = findListIndex(listItems, listDates[i].id);
if (index != null) listItems[index].savedDate = listDates[i].savedDate;
}
return listItems;
}
function findListIndex(listItems, id) {
for (var i = 0; i < listItems.length; i++) {
if (listItems[i].id == id) return i;
}
return null;
}
The first one, mergeDates, takes your first list wich contains the date, the second list, listItems, is the list of your items.
I loop the list with dates, and for each items in it, i call a second function that return the index of the same element in the second list, so findListIndex will search all element and return it's index when he find the same id.
Now the function mergeDates, with the newly found index, will add the value savedDate to your listItems and make it equals to the one on the listDates !
Then the function return the list with all the info of the items, including the dates!
Here is how to call the function:
var listWithDate = mergeDates(savedItems, items);
Hope it helps !
Related
I have this array of objects. I have to create a new array with filtered results. I tried using the filter() method, but something doesn't go right, and the second array is empty.
Code for the original array:
#foreach (var item in list)
{
#:newsObj.push({
#:Id:#item.Id,
#:Title: "#item.Title",
#:FeaturedImage: "#item.FeaturedImage",
#:DateFormated: "#item.DateFormated",
#:Summary: "#item.Summary",
#:Category: "#foreach (var cat in #item.Category) {#(cat.Title+" ") } "});
}
And then code for filtering into the next one. Data filters based on the matching category:
newsObjFiltered = newsObj.filter(category => category.Category == selectedClass);
I'm going to pre-face this with saying i'm not sure this is the best approach so other approaches are greatly appreciated
End Goal: To store a list of products and the toppings purchased by calling the woocommerce API and using the response data
I'm calling the woocommerce REST api that provides me a good chunk of JSON data back. In the JSON are line_items. These are the products purchased. Nested in line_items are meta_data, this is the toppings for example tomato or sauce.
Attached an image of the JSON
So what i'm trying to do is create something like this
var testOrderItems =
[{
title: "Fried Chicken Burger",
meta: [
"Lettuce",
"cheese slice",
"kethcup"
]
},
{
title: "Beef Burger",
meta: [
"Lettuce",
"cheese slice",
"kethcup"
]
}
]
which will follow my schema for oder items
var orderItems = new Schema({
title: {type: String, required: true},
meta: [{type: String}]
});
So to do this, i figured I would just do a forloop or foreach through the JSON to get all the product names and their meta. Getting actual values is easy. The hard part is creating the array or JSON object that I can then store, i'm just not sure how to create it whilst in the loop. Below are a few things I tried
let fullData = JSON.parse(result)
//parsed response from woocommerce API call
fullData.line_items.forEach((product, index) => {
//for each line item get me the product
orderItems.push(product.name)
//var namey =
//push the product name to the orderItemsArray
product.meta_data.forEach(function(meta) {
//checks for string as one of the plug-ins fills the meta with more nested information and we only want the top level string
if (typeof meta.value === 'string' || meta.value instanceof String)
// it's a string
orderItems.push(meta.value)
//Onbviously won't nest the meta with the product name just on new lines
})
});
The I thought I could do it in for loops by storing an ID ref as "i" and being able to re-reference this later in the nested loop to add the meta, i got a little lost with this
var length = fullData.line_items.length
for (let i = 0; i < length; i++) {
// console.log(i);
console.log(fullData.line_items[i].name)
for (let j = 0; j < fullData.line_items[i].meta_data.length; j++) {
var metaValue = fullData.line_items[i].meta_data[j].value
if (typeof metaValue === 'string' || metaValue instanceof String) {
console.log(fullData.line_items[i].meta_data[j].value);
stringMeta = fullData.line_items[i].meta_data[j].value
//this works but has drawbacks
//1 obviously just overwrites itself each time
//2 will stop at the end of meta so won't add items without meta
finalOrderItems = {
id: i,
name: fullData.line_items[i].name,
meta: [stringMeta]
}
}
}
}
and thats where I am, feels like this should be incredibly easy but can't quite grasp it at the moment.
You could simply create the object that represents your schema first, then return it from a map of your json Object. So, it would look like the following:
let testOrderItems = fullData.line_items.map((product)=>{
let obj = { name: product.name };
obj.meta = product.meta_data.map((meta)=>{
if (typeof meta.value === 'string' || meta.value instanceof String)
return meta.value;
}).filter((value)=>!!value);
return obj;
})
console.log(testOrderItems);
Although, the if statement seems a little redundant, since the woocommerce api will simply either have meta or not. However, you may have some plugin or something which is adding more information to the meta area so i've kept it in my example.
This looks like a job for map and reduce not forEach. map will map each object of line_items into a new object and reduce will group and organize the metas by key for each object:
var orderItems = fullData.line_items.map(function(product) { // map each product in line_items
return { // into a new object
title: product.name, // with title equals to the current product's name
meta: product.meta_data.reduce(function(acc, meta) { // and metas accumulated from each meta object in the current product's meta_data array
acc[meta.key] = acc[meta.key] || []; // first, check if there is an array for the current meta's key in the group object 'acc', if not create one
acc[meta.key].push(meta.value); // add the current meta's value to that array
return acc;
}, {})
}
});
Shorter using arrow functions:
var orderItems = fullData.line_items.map(product => ({
title: product.name,
meta: product.meta_data.reduce((acc, meta) => {
acc[meta.key] = acc[meta.key] || [];
acc[meta.key].push(meta.value);
return acc;
}, {})
}));
I have a JavaScript Array of Objects, on a button click I push an object into the array and then use that as a datasource for a grid. The issue I am facing is that initially the first object in the array is all blank values and when I load the grid I have a blank row because of the empty object... How do I remove that empty object from the array before I load the grid?
Here is the array
var gridData = {
step3GridData: [{ Description: "", Color: "", SqSiding: "" }]
};
and on a button click I am pushing a new object to the array
gridData.step3GridData.push({ Description: $("#InfoInsul").text(), Color: $("#ddGetInsulationMaterialColor").val(), SqSiding: $("#ddInsulationSquares").val() });
LoadStep3(gridData.step3GridData);
As mentioned, I need to remove that empty object before I bind the load with the array. How would I go about doing this?
Use splice. If you are certain it is always the first item in the array, you can do:
if (gridData.length && Object.keys(gridData[0]).length === 0) {
gridData.splice(0, 1);
}
If you are not certain about its position, you can traverse the array and remove the first empty object:
for (const [idx, obj] of gridData.entries()) {
if (Object.keys(obj).length) === 0) {
gridData.splice(idx, 1);
break;
}
}
First, initialize your array like this:
var gridData = {
step3GridData: [] // empty array
};
Then when you are pushing a new object, check if the inputs are filled like this:
var desc = $("#InfoInsul").text(); // this seems unnecessary as this is not left to the user to fill (if I'm assuming right then don't check if this is empty)
var col = $("#ddGetInsulationMaterialColor").val();
var sqs = $("#ddInsulationSquares").val();
if(desc.length && col.length && sqs.length) { // if desc is not empty and col is not empty and sqs not empty then add an object
gridData.step3GridData.push({ Description: desc, Color: col, SqSiding: });
}
Now if the user left something empty, the object won't get pushed, thus there will be no empty objects. You can make use of else to alert a message saying that the user left some input blank.
I have returned an object from an ajax call that is the combination of two different arrays' of objects. One is Jobs and the second is the corresponding Customer Records for those jobs. The returned object is formatted like so..
{ "jobs" : [
{jobID: 1,
jobLocation: here
},
{jobID: 2,
jobLocation: there
}
],
"customers" : [
{customerID:1,
customerName:Tom
},
{customerID:2,
customerName:Sally
}
]
}
The items in the job array are sequentially related to the customers in the customer array. (i.e. the first customer owns the first job) How can I iterate or parse then iterate over this object to make list objects<li>'s that have are composed of a field from the jobs array and a field from the corresponding object of the customers array? thank you
A plain, old for-loop might do the job:
var customers = obj.customers;
var jobs = obj.jobs;
var $ul = $("<ul></ul>");
for (var i = 0; i < customers.length; i++) {
var customer = customers[i];
var job = jobs[i];
var $li = $("<li></li>").text(customer.customerName + " - " + job.jobLocation);
$li.appendTo($ul);
}
$("#result").append($ul);
See http://jsfiddle.net/XpQms/
Part of my json Array
var videos = $j.parseJSON('
[
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"private",
"id":"803641223" },
{ "privacy":"public",
"id":"1300612600" }, ......
When I console.log the element I'm getting
[Object, Object, Object, …]
0: Object
privacy: "public"
id: "1169341693"
1: Object
privacy: "private"
id: "803641223"
2: Object
privacy: "public"
id: "1300612600"
I also have a unique id I want to search for
var uniqueId = 803641223;
I want to find, in my videos array, the right id, and delete that whole array element. So In that case, I want my final videos array to contain only 2 object, instead of 3 :
var videos = $j.parseJSON('
[
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"public",
"id":"1300612600" }, ......
My problem is how to get in the array to do my splice. I prefer to do it with jQuery
Any help please?
You can use grep :
videos = $.grep(videos, function(e) { return e.id!='803641223' });
In vanilla JavaScript you could have used the similar filter function but it's not supported by IE8.
Please note that videos is a JavaScript array, it's not a JSON array, even if it was made by parsing a JSON string.
A non-jQuery solution that modifies the array in place:
var uniqueId = 803641223;
var videos = [
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"private",
"id":"803641223" },
{ "privacy":"public",
"id":"1300612600" }
];
function cleaner(arr, id) {
for (var i = 0; i < videos.length; i++) {
var cur = videos[i];
if (cur.id == uniqueId) {
arr.splice(i, 1);
break;
}
}
}
cleaner(videos, uniqueId);
http://jsfiddle.net/4JAww/1/
Note that this modifies the original array in place, such that the original videos array will have the items you want, and the one that matched the uniqueId will be gone (forever). So it depends on whether you want to be able to access the original array ever again, or are okay with modifying it.
It just loops through the elements of the array, compares the item's id property to the uniqueId value, and splices if they match. I use break; immediately after the splice because you seem to imply that the uniqueId can/should only appear once in the array since it's...unique.
Hello you can remove element with javascript splice function...
videos.items.splice(1, 3); // Removes three items starting with the 2nd,
It worker for me.
arrList = $.grep(arrList, function (e) {
if(e.add_task == addTask && e.worker_id == worker_id) {
return false;
} else {
return true;
}
});
It returns an array without that object.
Hope it helps.