Split AJAX response (JSON) - javascript

How would I split the following AJAX response into three separate objects based on the attribute 'product_range' using JS/jQuery, i.e. one object array for all 'range-1' products, one for 'range-2' and so on?
[
{
title: "Product 1",
price: "12.00",
product_range: "range-1"
},
{
title: "Product 2",
price: "12.00",
product_range: "range-2"
},
{
title: "Product 3",
price: "12.00",
product_range: "range-3"
}
]

I would just use reduce and push items into an object that holds arrays.
var items = [
{
title: "Product 1",
price: "12.00",
product_range: "range-1"
},
{
title: "Product 2",
price: "12.00",
product_range: "range-2"
},
{
title: "Product 3",
price: "12.00",
product_range: "range-3"
}
];
var grouped = items.reduce( function (obj, item) {
if (!obj[item.product_range]) obj[item.product_range] = [];
obj[item.product_range].push(item);
return obj;
}, {});
console.log(grouped);
console.log(grouped["range-1"]);

Use the method "filterByProductRange" to filter out the data by product_range.
var obj = [
{
title: "Product 1",
price: "12.00",
product_range: "range-1"
},
{
title: "Product 2",
price: "12.00",
product_range: "range-2"
},
{
title: "Product 3",
price: "12.00",
product_range: "range-3"
}
];
function filterByProductRange(data, product_range) {
return data.filter(function(item) { return item['product_range'] == product_range; });
}
var range1= filterByProductRange(obj, 'range-1');
console.log(range1);

if you mean grouping your data by product_range, then:
//json is your json data
var result = {};
for(var i=0; i<json.length;i++)
{
if(result[json[i].product_range] === undefined) result[json[i].product_range] = [];
result[json[i].product_range].push(json[i]);
}

Something like this should group by range.
var ranged = {};
var data = [{
title: "Product 1",
price: "12.00",
product_range: "range-1"
}, {
title: "Product 2",
price: "12.00",
product_range: "range-2"
}, {
title: "Product 3",
price: "12.00",
product_range: "range-3"
}]
$.each(data, function(i, x) {
if (ranged[x.product_range]) {
ranged[x.product_range].push(x);
} else {
ranged[x.product_range] = [x];
}
});
console.log(JSON.stringify(ranged));
You should then be able to retrieve all object for a given range by querying the ranged object.

You can use $.map() to achieve a similar result.
var range1 = new Object(),
range2 = new Object(),
range3 = new Object();
$.map(data, function(d){
if (d.product_range === "range-1") {
for (var i in d) {
range1[i] = d[i];
}
}
});
Where data is your object array.
Here's a simple fiddle to demonstrate this.

Related

Parse array of objects recursively and filter object based on id

i have this array of objects : getCategory (variable)
[
{
"id": "20584",
"name": "Produits de coiffure",
"subCategory": [
{
"id": "20590",
"name": "Coloration cheveux",
"subCategory": [
{
"id": "20591",
"name": "Avec ammoniaque"
},
{
"id": "20595",
"name": "Sans ammoniaque"
},
{
"id": "20596",
"name": "Soin cheveux colorés"
},
{
"id": "20597",
"name": "Protection"
},
{
"id": "20598",
"name": "Nuancier de couleurs"
}
]
},
{
"id": "20593",
"name": "Soins cheveux",
"subCategory": [
{
"id": "20594",
"name": "Shampooing"
},
{
"id": "20599",
"name": "Après-shampooing"
},
{
"id": "20600",
"name": "Masques"
},
and i tried everything i could search in stackoverflow ..
lets say on this array i want to get recursively and object with the specified id .. like 20596 and it should return
{
"id": "20596",
"name": "Soin cheveux colorés"
}
The logic way i am doing is like this :
var getSubcategory = getCategory.filter(function f(obj){
if ('subCategory' in obj) {
return obj.id == '20596' || obj.subCategory.filter(f);
}
else {
return obj.id == '20596';
}
});
dont know what else to do .
Thanks
PS : I dont use it in browser so i cannot use any library . Just serverside with no other library . find dont work so i can only use filter
You need to return the found object.
function find(array, id) {
var result;
array.some(function (object) {
if (object.id === id) {
return result = object;
}
if (object.subCategory) {
return result = find(object.subCategory, id);
}
});
return result;
}
var data = [{ id: "20584", name: "Produits de coiffure", subCategory: [{ id: "20590", name: "Coloration cheveux", subCategory: [{ id: "20591", name: "Avec ammoniaque" }, { id: "20595", name: "Sans ammoniaque" }, { id: "20596", name: "Soin cheveux colorés" }, { id: "20597", name: "Protection" }, { id: "20598", name: "Nuancier de couleurs" }] }, { id: "20593", name: "Soins cheveux", subCategory: [{ id: "20594", name: "Shampooing" }, { id: "20599", name: "Après-shampooing" }, { id: "20600", name: "Masques" }] }] }];
console.log(find(data, '20596'));
console.log(find(data, ''));

Select nested array object and replace it

I got an array (as result of a mongoDB query) with some elements like this:
{
"_id": "ExxTDXJSwvRbLdtpg",
"content": [
{
"content": "First paragraph",
"language":"en",
"timestamp":1483978498
},
{
"content": "Erster Abschnitt",
"language":"de",
"timestamp":1483978498
}
]
}
But I need to get just a single content field for each data array element, which should be selected by the language. So the result should be (assuming selecting the english content):
{
"_id": "ExxTDXJSwvRbLdtpg",
"content": "First paragraph"
}
instead of getting all the content data...
I tried to do it with find(c => c.language === 'en), but I don't know how to use this for all elements of the data array. Maybe it is also possible to get the data directly as a mongodb query??
You could iterate the array and replace the value inside.
var array = [{ _id: "ExxTDXJSwvRbLdtpg", content: [{ content: "First paragraph", language: "en", timestamp: 1483978498 }, { content: "Erster Abschnitt", language: "de", timestamp: 1483978498 }] }];
array.forEach(a => a.content = a.content.find(c => c.language === 'en').content);
console.log(array);
Version with check for content
var array = [{ _id: "ExxTDXJSwvRbLdtpg", content: [{ content: "First paragraph", language: "en", timestamp: 1483978498 }, { content: "Erster Abschnitt", language: "de", timestamp: 1483978498 }] }, { _id: "no_content" }, { _id: "no_english_translation", content: [{ content: "Premier lot", language: "fr", timestamp: 1483978498 }, { content: "Erster Abschnitt", language: "de", timestamp: 1483978498 }] }];
array.forEach(function (a) {
var language;
if (Array.isArray(a.content)) {
language = a.content.find(c => c.language === 'en');
if (language) {
a.content = language.content;
} else {
delete a.content;
}
}
});
console.log(array);
Given that _id and language are input variables, then you could use this aggregate command to get the expected result:
db.collection.aggregate([{
$match: {
_id: _id,
}
}, {
$unwind: '$content'
}, {
$match: {
'content.language': language,
}
}, {
$project: {
_id: 1,
content: '$content.content'
}
}])
var aobjs = [{
"_id": "ExxTDXJSwvRbLdtpg",
"content": [
{
"content": "First paragraph",
"language":"en",
"timestamp":1483978498
},
{
"content": "Erster Abschnitt",
"language":"de",
"timestamp":1483978498
}
]
}];
var result = aobjs.map(o => ({ id: o._id, content: o.content.find(c => c.language === 'en').content }));
This returns an object for each with just id and content. In this example, result would be:
[ { id: 'ExxTDXJSwvRbLdtpg', content: 'First paragraph' } ]

group by nested array property in JavaScript

I have a json object as below in my web application. It's an array of product objects and each product object has a category property which contains an array of categories that the product belongs to.
var products = [
{
"id":1,
"name":"Product 1",
"price":10,
"category":[
{
"id":10,
"name":"Category 1"
},
{
"id":20,
"name":"Category 2"
}
]
},
{
"id":2,
"name":"Product 2",
"price":20,
"category":[
{
"id":20,
"name":"Category 2"
},
{
"id":30,
"name":"Category 3"
}
]
}
]
So now I want to display them grouped by categories so the end result will look like below. I am already using Underscore.js in my project so it will be good if I can use it to achieve this.
var categories = [
{
"id":10,
"name":"Category 1",
"products":[
{
"id":1,
"name":"Product 1",
"price":10
}
]
},
{
"id":20,
"name":"Category 2",
"products":[
{
"id":1,
"name":"Product 1",
"price":10
},
{
"id":2,
"name":"Product 2",
"price":20,
}
]
},
{
"id":30,
"name":"Category 3",
"products":[
{
"id":2,
"name":"Product 2",
"price":20,
}
]
}
]
I'm not entirely sure whether there is an out-of-the-box solution to this problem with underscore, however solving this by hand shouldn't be too hard, either:
var categoriesIndexed = {};
var categories = [];
products.forEach(function(product) {
product.category.forEach(function(category) {
// create a new category if it does not exist yet
if(!categoriesIndexed[category.id]) {
categoriesIndexed[category.id] = {
id: category.id,
name: category.name,
products: []
};
categories.push(categoriesIndexed[category.id]);
}
// add the product to the category
categoriesIndexed[category.id].products.push({
id: product.id,
name: product.name,
price: product.price
});
});
});
here is what I would do
var categories = [];
var cat = new Map();
var addUniqueCategory(category) { /* determine if category is already in list of categories, if not add it to categories */ };
products.each (function (item) {
item.categories.each(function (c) {
if (!cat.has(c.name)) cat.set(c.name, []);
var list = cat.get(c.name);
list.push( { id: item.id, name: item.name, price: item.price });
addUniqueCategory(c);
});
});
categories.each( function (c) {
var list = cat.get(c.name);
if (!c.products) c.products = [];
c.products.splice( c.length, 0, list);
});
roughly, I'm on a phone

Manipulating javascript object with underscore

I have a Javascript object with a format like below
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub1",
"id" : "1",
"items":[
{
"title":"Ajax request 1",
},
{
"title":"Ajax request 2",
}
]
},
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
There are n 'Groups', n 'subGroups' and n 'items'.
What I want to do firstly is get all the items from a particular group based on id. This is achieved using:
_.each(items.Groups, function(o) {
result = _.where(o.SubGroups, {
'id': '1'
});
});
which returns
"items":[{"title":"Ajax request 1",},{"title":"Ajax request 2",}]
Then I want to get the rest of the data, excluding the items and parent group I have just retrieved.
I tried this:
_.each(items.Groups, function(o) {
arr = _.without(o.SubGroups, _.findWhere(o.SubGroups, {id: '2'}));
});
But this only returns me the items like this:
{
"title":"sub2",
"id" : "2",
"items":[{"title":"Ajax request 3"},{"title":"Ajax request 4",}]
}
whereas what I need is this:
"items":
{
"Groups":[
{
"title":"group 1",
"SubGroups":[
{
"title":"sub2",
"id" : "2",
"items":[
{
"title":"Ajax request 3",
},
{
"title":"Ajax request 4",
}
]
}
]
}
]
Just try this:
_.each(items.Groups, function(o) {
arr = _.without(o, _.findWhere(o.SubGroups, {id: '2'}));
});
o should be enough => you want to get Groups and not SubGroups.
Following is a pure JS implementation:
JSFiddle.
var data = {
"Groups": [{
"title": "group 1",
"SubGroups": [{
"title": "sub1",
"id": "1",
"items": [{
"title": "Ajax request 1",
}, {
"title": "Ajax request 2",
}]
}, {
"title": "sub2",
"id": "2",
"items": [{
"title": "Ajax request 3",
}, {
"title": "Ajax request 4",
}]
}]
}]
}
var items = [];
var group = [];
data.Groups.forEach(function(o) {
var _tmp = JSON.parse(JSON.stringify(o));
_tmp.SubGroups = [];
o.SubGroups.forEach(function(s) {
if (s.id == "1") {
items.push(s.items);
} else {
_tmp.SubGroups.push(s);
group.push(_tmp)
}
});
});
function printObj(label, obj) {
document.write(label + "<pre>" + JSON.stringify(obj, 0, 4) + "</pre>")
}
printObj("group", group);
printObj("items", items);
Using underscore and using your logic to filter all subgroups:
//array to store subgroup with ID 1
var results = [];
var d = _.each(data.items.Groups, function(o) {
result = _.where(o.SubGroups, {
'id': '1'
});
//add to results array
results.push(result);
});
//make a clone of the earlier object so that you get the parent structure.
var data1 = _.clone(data);
//set the filtered results to the group
data1.items.Groups = results;
//your data as you want
console.log(data1)
Working code here

Sorting an array of objects with multiple entries

I would like to rearrange an array of objects in javascript, which looks like this:
[{ year: "1950-12-20", product: ["product 1", "product 2, "product 3"] }, { year: "1951-12-20", product: ["product 3", "product 2"] }, { year: "1952-12-20", product: ["product 3", "product 4"] }]
so that I get two arrays, one with the products and one with the years when they appear.
a = ["product 1", "product 2", "product 3", "product 4"]
b = ["1950-12-20", [ "1950-12-20, "1951-12-20"],["1950-12-20", "1951-12-20", "1952-12-20"],"1952-12-20"]
I have tried to loop through each object through nestled for-loops, but how do I treat the array of strings in the object array in a nice way?
I don't know what kind of loop you have tested, but this type of code is not so long for what has to be done :
var data = [{ year: "1950-12-20", product: ["product 1", "product 2", "product 3"] }, { year: "1951-12-20", product: ["product 3", "product 2"] }, { year: "1952-12-20", product: ["product 3", "product 4"] }];
var nbData = data.length, iData;
var years = [], products = [], dictProductsYear = {};
var nbProducts, iProduct, p;
// Loop through years
for(iData = 0; iData < nbData; iData ++) {
products = data[iData].product;
nbProducts = products.length;
// Add the current year to the concerned products
for(iProduct = 0; iProduct < nbProducts; iProduct ++) {
p = products[iProduct];
// Registered product
if(dictProductsYear[p]) dictProductsYear[p].push(data[iData].year);
// Unregistered one
else dictProductsYear[p] = [ data[iData].year ];
}
}
var yearList = [], productList = [];
// Flatten the dictionary in 2 lists
for(p in dictProductsYear) {
productList.push(p);
yearList.push(dictProductsYear[p]);
}
This looks a bit like #Samuel Caillerie's code, but is more concise:
var data = [{ year: "1950-12-20", product: ["product 1", "product 2", "product 3"] }, { year: "1951-12-20", product: ["product 3", "product 2"] }, { year: "1952-12-20", product: ["product 3", "product 4"] }];
var yearsByProd = {};
for (var i=0; i<data.length; i++) {
var prod = data[i].product;
for (var j=0; j<prod.length; j++) {
if (prod[j] in yearsByProd)
yearsByProd[prod[j]].push(data[i].year);
else
yearsByProd[prod[j]] = [data[i].year];
}
}
var a, b;
b = (a = Object.keys(yearsByProd).sort()).map(function(prod) {
// add an if-else-statement here if you want to extract single years from their array
return yearsByProd[prod];
});

Categories

Resources