Related
I need to convert below unformatted JSON format into formatted input. We need to find id's similar to parent id for different items inside array element of object and then need to push it into children to that id. Below is my code that needs to transform
Input
{
"0": [
{
"id": 10,
"title": "House",
"level": 0,
"children": [],
"parent_id": null
}
],
"1": [
{
"id": 12,
"title": "Red Roof",
"level": 1,
"children": [],
"parent_id": 10
},
{
"id": 18,
"title": "Blue Roof",
"level": 1,
"children": [],
"parent_id": 10
}
],
"2": [
{
"id": 17,
"title": "Blue Windoww",
"level": 2,
"children": [],
"parent_id": 12
},
{
"id": 16,
"title": "Door",
"level": 2,
"children": [],
"parent_id": 13
}
]
}
Output
[
{
"id": 10,
"title": "House",
"level": 0,
"children": [
{
"id": 12,
"title": "RedRoofff",
"level": 1,
"children": [
{
"id": 17,
"title": "Blue Windoww",
"level": 2,
"children": [],
"parent_id": 12
}
],
"parent_id": 10
},
{
"id": 18,
"title": "Blue Roof",
"level": 1,
"children": [],
"parent_id": 10
},
{
"id": 13,
"title": "Wall",
"level": 1,
"children": [
{
"id": 16,
"title": "Door",
"level": 2,
"children": [],
"parent_id": 13
}
],
"parent_id": 10
}
],
"parent_id": null
}
]
Please find the solution to above problem.
first, we track the node with Id and then we update the children array like this.
(btw, your input have a missing node, 13)
const input = {
"0": [{
"id": 10,
"title": "House",
"level": 0,
"children": [],
"parent_id": null
}, {
"id": 13,
"title": "Wall",
"level": 0,
"children": [],
"parent_id": null
}],
"1": [{
"id": 12,
"title": "Red Roof",
"level": 1,
"children": [],
"parent_id": 10
},
{
"id": 18,
"title": "Blue Roof",
"level": 1,
"children": [],
"parent_id": 10
},
],
"2": [{
"id": 17,
"title": "Blue Windoww",
"level": 2,
"children": [],
"parent_id": 12
},
{
"id": 16,
"title": "Door",
"level": 2,
"children": [],
"parent_id": 13
},
]
};
const results = [];
const mapId2Node = Object.values(input).reduce((acc, vals) => {
vals.forEach(val => {
acc[val.id] = val;
if (val.parent_id === null) {
results.push(val);
}
});
return acc;
}, {});
Object.values(input).forEach(vals => {
vals.forEach(val => {
if (val.parent_id !== null) {
mapId2Node[val.parent_id].children.push(val);
}
});
});
conosle.log(results);
I'm manipulating some javascript objects and I want to know if is there a more efficient and easy way to process my data.
I already do that, but I'm a beginner in js.
I have four objects with this structure: basically there is an array of blocks and any object has a different number of blocks. In every block, in the features attribute, I have another array with some features.
Then I have another object, and I have to remove from this object (I call it structure) blocks and features that are not present in my four initial object.
This is a sample product object
[
{
"ID": 16293,
"SortNo": "20",
"FeatureGroup": {
"ID": "148",
"Name": {
"Value": "Design",
"Language": "IT"
}
},
"Features": [
{
"Localized": 0,
"ID": "155744521",
"Type": "dropdown",
"Value": "Round",
"CategoryFeatureId": "85327",
"CategoryFeatureGroupID": "16293",
"SortNo": "155",
"PresentationValue": "Rotondo",
"RawValue": "Round",
"LocalValue": [],
"Description": "The external form",
"Mandatory": "1",
"Searchable": "0",
"Feature": {
"ID": "9397",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Forma",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "155655523",
"Type": "multi_dropdown",
"Value": "White",
"CategoryFeatureId": "85298",
"CategoryFeatureGroupID": "16293",
"SortNo": "90",
"PresentationValue": "Bianco",
"RawValue": "White",
"LocalValue": [],
"Description": "The colour of the housing",
"Mandatory": "1",
"Searchable": "1",
"Feature": {
"ID": "10059",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Colore struttura",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "155655525",
"Type": "multi_dropdown",
"Value": "White",
"CategoryFeatureId": "85301",
"CategoryFeatureGroupID": "16293",
"SortNo": "80",
"PresentationValue": "Bianco",
"RawValue": "White",
"LocalValue": [],
"Description": "The colour of the band",
"Mandatory": "1",
"Searchable": "1",
"Feature": {
"ID": "11025",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Colore cinturino",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "219617494",
"Type": "y_n",
"Value": "Y",
"CategoryFeatureId": "168947",
"CategoryFeatureGroupID": "16293",
"SortNo": "-6",
"PresentationValue": "Sì",
"RawValue": "Y",
"LocalValue": [],
"Description": "The product is protected from water",
"Mandatory": "0",
"Searchable": "0",
"Feature": {
"ID": "7509",
"Sign": "",
"Measure": {
"ID": "26",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Resistente all'acqua",
"Language": "IT"
}
}
}
]
},
{
"ID": 34567,
"SortNo": "20",
"FeatureGroup": {
"ID": "184",
"Name": {
"Value": "Prestazione",
"Language": "IT"
}
},
"Features": [
{
"Localized": 0,
"ID": "155744528",
"Type": "y_n",
"Value": "N",
"CategoryFeatureId": "94697",
"CategoryFeatureGroupID": "34567",
"SortNo": "800",
"PresentationValue": "No",
"RawValue": "N",
"LocalValue": [],
"Description": "La Frequenza modulare radio produce la miglior recezione di qualsiasi canale radio. Quando viene usato un auricolare, produce un effetto di suono da stereo r",
"Mandatory": "1",
"Searchable": "0",
"Feature": {
"ID": "2172",
"Sign": "",
"Measure": {
"ID": "26",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Radio FM",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "155744530",
"Type": "multi_dropdown",
"Value": "Not supported",
"CategoryFeatureId": "85357",
"CategoryFeatureGroupID": "34567",
"SortNo": "500",
"PresentationValue": "Non supportato",
"RawValue": "Not supported",
"LocalValue": [],
"Description": "Types of memory cards which can be used with this product.",
"Mandatory": "1",
"Searchable": "0",
"Feature": {
"ID": "730",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Tipi schede di memoria",
"Language": "IT"
}
}
}
]
}
]
Here i loop my initial objects (this.compare_products) to extract, in two arrays (featureGroupIds - featureIds) the ID of my block and the CategoryFeatureId
let featureGroupIds = []
let featureIds = []
this.compare_products.forEach((object) => {
featureGroupIds = featureGroupIds.concat(FeaturesGroups.map(o => o.ID))
featureIds = featureIds.concat(FeaturesGroups.map(o => o.Features.map(o => o. CategoryFeatureId))).flat(2)
})
The two arrays, featureGroupIds and featureIds are now filled with every block ID and every CategoryFeatureId present in my four object.
Now I have to filter the object I call "structure" to remove the block and the features with an ID that is not present in my arrays.
This is my structure, and as you can see is similar.
[
{
"name": "Display",
"data": {
"id": 34566,
"category_id": 2647
},
"features": [
{
"name": "Tipo di display",
"data": {
"id": 85325,
"category_id": 2647,
"feature_id": 9104,
"category_feature_group_id": 34566,
"order": 10100140
}
},
{
"name": "Touch screen",
"data": {
"id": 85331,
"category_id": 2647,
"feature_id": 4963,
"category_feature_group_id": 34566,
"order": 10100129
}
},
{
"name": "Dimensioni schermo",
"data": {
"id": 158002,
"category_id": 2647,
"feature_id": 3544,
"category_feature_group_id": 34566,
"order": 100149
}
},
{
"name": "à di Pixel",
"data": {
"id": 85347,
"category_id": 2647,
"feature_id": 13246,
"category_feature_group_id": 34566,
"order": 100147
}
},
{
"name": "Tipo di vetro",
"data": {
"id": 94704,
"category_id": 2647,
"feature_id": 7610,
"category_feature_group_id": 34566,
"order": 100050
}
}
]
},
{
"name": "Altre caratteristiche",
"data": {
"id": 34569,
"category_id": 2647,
"feature_group_id": 146,
"name": null,
"order": 0
},
"features": [
{
"name": "inside",
"data": {
"id": 110410,
"category_id": 2647,
"feature_id": 18688,
"category_feature_group_id": 34569,
"order": 100000
}
}
]
}
]
Here is my function
structure = structure.filter(featureGroup => this.featureGroupIds.includes(featureGroup.data.id));
structure.map((object) => {
object.features.filter(feature => this.featureIds.includes(feature.data.feature_id))
})
this.featureIds and this.featureGroupIds are the array with the group IDS and with the feature IDS.
Is there a more efficient way to do this?
This is an example of an api response
[
{
"id": 1,
"name": "Medicine1",
"status": true,
"location": "E1-2",
"genericName": "Medicine1 Generic name",
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 25,
"percentage": null
},
{
"id": 2,
"name": "Medicine2",
"status": true,
"location": "E1-5",
"genericName": "Medicine2 Generic",
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 2,
"name": "Cremas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 500,
"percentage": null
},
{
"id": 3,
"name": "Medicine3",
"status": true,
"location": "E1-2",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 3,
"name": "Unguentos"
},
"measure": {
"id": 3,
"unit": "Libras",
"abbreviation": "lb"
},
"quantity": 5,
"percentage": null
},
{
"id": 4,
"name": "Medicine4",
"status": true,
"location": "E5-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 2,
"unit": "Kilogramos",
"abbreviation": "kg"
},
"quantity": 5,
"percentage": null
},
{
"id": 5,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
},
{
"id": 6,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
},
{
"id": 7,
"name": "Medicine6",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
},
{
"id": 8,
"name": "Medicine7",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": 3,
"name": "Falcon"
},
"presentation": {
"id": 4,
"name": "Gotas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
}
]
As you can see, the laboratory, percentage and genericName keys can have null value.
I need to filter this response according to a criteria that should be compared with each value
Here is the filter code
const criteria = 'some text';
fetchResource('medicines').then(medicines => {
const results = medicines.filter(medicine => {
return (
medicine.name.toLowerCase().includes(criteria) ||
medicine.genericName.toLowerCase().includes(criteria) ||
medicine.presentation.name
.toLowerCase()
.includes(criteria) ||
medicine.measure.unit.toLowerCase().includes(criteria) ||
medicine.measure.abbreviation
.toLowerCase()
.includes(criteria) ||
medicine.location.toLowerCase().includes(criteria)
);
});
const helper = makeHelper();
helper.render(results);
});
In backend, I thought about excluding the mentioned keys from the response when they do not have values. I have not tried yet but I understand that would work
I appreciate your advice on how to deal with this case on the client's side
There are other answers here that suggest using JSON.stringify to convert the entire object to a string, but that's not a great solution. It would make it impossible to search for generic, because every object has a property named genericName. There is another way to use stringify that's a bit more graceful, and that's to take advantage of the replacer callback.
For example:
const results = medicines.filter(m => {
var isMatch = false;
JSON.stringify(m, (key, value) => {
if (typeof value === "string" && value.toLowerCase().includes(criteria)) {
isMatch = true;
}
return value;
});
return isMatch;
});
results will contain only those entries from medicines that contain some value that is a string that matches the given filter. You can extend this logic to include numeric values, such as id, or exclude certain keys you're not interested in, such as abbreviation.
Here's a quick demo implementing some more advanced logic. You'll of course want to tweak it to suit your exact needs:
const medicines = [{
"id": 1,
"name": "Medicine1",
"status": true,
"location": "E1-2",
"genericName": "Medicine1 Generic name",
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 25,
"percentage": null
},
{
"id": 2,
"name": "Medicine2",
"status": true,
"location": "E1-5",
"genericName": "Medicine2 Generic",
"laboratory": { "id": null, "name": null },
"presentation": { "id": 2, "name": "Cremas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 500,
"percentage": null
},
{
"id": 3,
"name": "Medicine3",
"status": true,
"location": "E1-2",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 3, "name": "Unguentos" },
"measure": { "id": 3, "unit": "Libras", "abbreviation": "lb" },
"quantity": 5,
"percentage": null
},
{
"id": 4,
"name": "Medicine4",
"status": true,
"location": "E5-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 2, "unit": "Kilogramos", "abbreviation": "kg" },
"quantity": 5,
"percentage": null
},
{
"id": 5,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
},
{
"id": 6,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
},
{
"id": 7,
"name": "Medicine6",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
},
{
"id": 8,
"name": "Medicine7",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": 3, "name": "Falcon" },
"presentation": { "id": 4, "name": "Gotas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
}
];
const btn = document.getElementById("go");
const inp = document.getElementById("search");
btn.addEventListener('click', () => {
const criteria = inp.value.toLowerCase();
const results = medicines.filter(m => {
var isMatch = false;
JSON.stringify(m, (key, value) => {
// Search 'id' values
if (key === "id" && value !== null && value.toString().includes(criteria)) {
isMatch = true;
// Ignore 'abbreviation'
} else if (key !== "abbreviation") {
// Search all other string values
if (typeof value === "string" && value.toLowerCase().includes(criteria)) {
isMatch = true;
}
}
return value;
});
return isMatch;
});
console.log(results);
});
<input id="search" type="search" placeholder="filter" /><button id="go">Go</button><br>
<code>
Currently your code will error on medicine.genericName.toLowerCase() if the genericName field isn't a string. To avoid that you could try one of the following instead:
Fall back to a default:
(medicine.genericName || '').toLowerCase().includes(criteria)
Check the value first:
(medicine.genericName && medicine.genericName.toLowerCase().includes(criteria))
Its a bit tough to figure out what you're trying to do with the example, but I'm assuming you want to check if the value of multiple keys in your API response contains a substring criteria?
If that's the case, you could try something like:
fetchResource('medicines').then(medicines => {
const results = medicines.filter(medicine => {
for (var key in medicine){
if((typeof(medicine[key] == 'string' || typeof(medicine[key] == 'int') && medicine[key].toString().toLowerCase().includes(criteria)){
return true
}
else if(typeof(medicine[key]) === 'object'){
for(var subkey in medicine[key]){
if((typeof(medicine[key][subkey]) == 'string' || typeof(medicine[key][subkey]) === 'int') && medicine[key][subkey].toString().toLowerCase().includes(criteria)){
return true
}
}
}
}
return false
})
})
This is obviously much cleaner than hard coding all of the property names.
As I told before, use a forEach in your array; following a function to filter;
Use JSON.stringify so you que see all properties in row;
Apply a pattern as criteria
var yourCriteria = ""; // or any Regex
var yourArray = [];
var newArray = [];
yourArray.forEach(function(e){
if (JSON.stringify(e).toLowerCase().indexOf(yourCriteria) < 0)
newArray.push(e);
})
I am not very good at implementing logic, hence seeking your help to implement the following logic.
I have an js object array in parent child format in the following way:
"categories": {
"data": {
"1": {
"id": 1,
"name": "Churches & Religious Org.",
"description": "Church\/religious organization",
"parent": 267,
"icon": "home"
},
"2": {
"id": 2,
"name": "Bands & Musicians",
"description": "Musician\/band",
"parent": 259,
"icon": "music-note"
},
"3": {
"id": 3,
"name": "Products & Services",
"description": "Product\/service",
"parent": 260,
"icon": "cube"
},
"4": {
"id": 4,
"name": "Actors & Directors",
"description": "Actor\/director",
"parent": 256,
"icon": "film-marker"
},
"5": {
"id": 5,
"name": "Athletes & Players",
"description": "Athlete",
"parent": 264,
"icon": "ios-americanfootball"
},
"6": {
"id": 6,
"name": "Movies",
"description": "Movie",
"parent": 256,
"icon": "ios-film"
},
"7": {
"id": 7,
"name": "TV Shows",
"description": "TV show",
"parent": 256,
"icon": "ios-videocam"
},
"8": {
"id": 8,
"name": "Professional Teams",
"description": "Sports Team",
"parent": 264,
"icon": ""
},
"9": {
"id": 9,
"name": "Politicians",
"description": "Politician",
"parent": 263,
"icon": ""
},
"10": {
"id": 10,
"name": "Food Products",
"description": "Food & Beverage Company",
"parent": 258,
"icon": ""
}};
You can see from above that I have elements in array where there is parent_id field.
Now basically I wanted to have a function which taking this input, create the modified version of this array where I will have the list of only elements which have any number of children.
That is if any element has parent_id without any children then in the list that element will not be added.
As commented; your "array" is not an array. You can use Object.values to turn it into an array. Then map that to only take parent value.
Now now have an array with values that are the id's of an item's parent. You can use these id's to create a new object with reduce, assuming that your object has a key that is it's id {id:{id:id:...},otherid:{id:otherid,...},...
var data = {
"1": {
"id": 1,
"name": "Churches & Religious Org.",
"description": "Church\/religious organization",
"parent": 2,
"icon": "home"
},
"2": {//2 doesn't have a parent
"id": 2,
"name": "Bands & Musicians",
"description": "Musician\/band",
"icon": "music-note"
},
"3": {
"id": 3,
"name": "Products & Services",
"description": "Product\/service",
"parent": 1,
"icon": "cube"
}
};
console.log(
Object.values(data)
.map(d=>d.parent)//get only parent values
.filter(parent=>parent)//remove those that don't have parent
//reduce to a new object that only contains items that had other items
// with it's id as their parent
.reduce(
(result,item)=>{
result[item]=data[item];
return result;
},
{}
)
)
Elements which have children.
var obj = {
"categories": {
"data": {
"1": {
"id": 1,
"name": "Churches & Religious Org.",
"description": "Church\/religious organization",
"parent": 267,
"icon": "home"
},
"2": {
"id": 2,
"name": "Bands & Musicians",
"description": "Musician\/band",
"parent": 259,
"icon": "music-note"
},
"3": {
"id": 3,
"name": "Products & Services",
"description": "Product\/service",
"parent": 260,
"icon": "cube"
},
"4": {
"id": 4,
"name": "Actors & Directors",
"description": "Actor\/director",
"parent": 256,
"icon": "film-marker"
},
"5": {
"id": 5,
"name": "Athletes & Players",
"description": "Athlete",
"parent": 264,
"icon": "ios-americanfootball"
},
"6": {
"id": 6,
"name": "Movies",
"description": "Movie",
"parent": 256,
"icon": "ios-film"
},
"7": {
"id": 7,
"name": "TV Shows",
"description": "TV show",
"parent": 256,
"icon": "ios-videocam"
},
"8": {
"id": 8,
"name": "Professional Teams",
"description": "Sports Team",
"parent": 264,
"icon": ""
},
"9": {
"id": 9,
"name": "Politicians",
"description": "Politician",
"parent": 263,
"icon": ""
},
"10": {
"id": 10,
"name": "Food Products",
"description": "Food & Beverage Company",
"parent": 258,
"icon": ""
}
}
}
}
var elemetsWithChildren = [];
for (var propt in obj.categories.data) {
if (elemetsWithChildren.indexOf(obj.categories.data[propt].parent) == -1) {
elemetsWithChildren.push(obj.categories.data[propt].parent);
}
}
console.log(elemetsWithChildren);
With this, you have an object with elements and numbers of children
var elemetsWithChildren = {};
for(var propt in obj.categories.data){
let parent = obj.categories.data[propt].parent
if(!elemetsWithChildren.hasOwnProperty(parent)){
elemetsWithChildren[parent] = 1;
}else{
elemetsWithChildren[parent]++;
}
}
console.log(elemetsWithChildren);
So I have this JSON Object. Let's call it var dataFetched
var dataFetched = {
"status": "ok",
"count": 4,
"count_total": 4,
"pages": 1,
"posts": [
{
"id": 57,
"type": "keyword",
"slug": "crime-scene-investigation-csi",
"url": "http://keyjargon.com/keyword/crime-scene-investigation-csi/",
"status": "publish",
"title": "Crime Scene Investigation (CSI)",
"title_plain": "Crime Scene Investigation (CSI)",
"content": "",
"excerpt": "",
"date": "2015-11-07 05:01:51",
"modified": "2015-11-07 05:01:51",
"categories": [
{
"id": 8,
"slug": "law",
"title": "Law",
"description": "",
"parent": 0,
"post_count": 1
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
},
{
"id": 50,
"type": "keyword",
"slug": "fx",
"url": "http://keyjargon.com/keyword/fx/",
"status": "publish",
"title": "FX",
"title_plain": "FX",
"content": "",
"excerpt": "",
"date": "2015-11-05 10:07:17",
"modified": "2015-11-05 10:22:10",
"categories": [
{
"id": 3,
"slug": "business",
"title": "Business",
"description": "",
"parent": 0,
"post_count": 2
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
},
{
"id": 48,
"type": "keyword",
"slug": "common-core",
"url": "http://keyjargon.com/keyword/common-core/",
"status": "publish",
"title": "Common CORE",
"title_plain": "Common CORE",
"content": "",
"excerpt": "",
"date": "2015-11-05 10:06:40",
"modified": "2015-11-07 04:58:06",
"categories": [
{
"id": 2,
"slug": "technology",
"title": "Technology",
"description": "",
"parent": 0,
"post_count": 3
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
},
{
"id": 46,
"type": "keyword",
"slug": "api",
"url": "http://keyjargon.com/keyword/api/",
"status": "publish",
"title": "API",
"title_plain": "API",
"content": "",
"excerpt": "",
"date": "2015-11-05 10:06:19",
"modified": "2015-11-05 10:21:47",
"categories": [
{
"id": 2,
"slug": "technology",
"title": "Technology",
"description": "",
"parent": 0,
"post_count": 3
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
}
]
}
I want to rearrange this result to link the Category title :
dataFetched.posts[i].categories[0].title
to the Post title :
dataFetched.post[i].title
so that each category displays all the posts titles related to it. I want my object (whether multi-demmensional array or another object) to be able to retrieve all the Posts titles related to the category.
Maybe something like this :
[Category1: {Post_titleA, PostTitleB, PostTitleC}, Category2: {PostTileF, PostTileX}, etc ] where each category can retrieve all its posts.( The format does not matter as long the Object with Category title X can retrieve all posts titles that belong to it ).
How do I do this in Javascript ? The result variable is not static but its format is the same as the one posted here.
This is what I tried so far.
// Function to sort unique values of an array
function sort_unique(arr) {
arr = arr.sort(function (a, b) { return a*1 - b*1; });
var ret = [arr[0]];
for (var i = 1; i < arr.length; i++) { // start loop at 1 as element 0 can never be a duplicate
if (arr[i-1] !== arr[i]) {
ret.push(arr[i]);
}
}
return ret;
}
//Define two arrays to be used for categories and Keywords
var keywords = [];
var industries = [];
//Fill up the categories(Industries) array and the keywords one
for ( var i = 0, iLen = dataFetched.count; i < iLen; i++) {
keywords[i] = dataFetched.posts[i].title;
industries[i] = dataFetched.posts[i].categories[0].title;
}
// Sort and eliminate duplication of category and keyword names
keywords = sort_unique(keywords);
industries = sort_unique(industries);
// Now time for trouble: Define a multi-dimmensional array that links each category/industry to its keywords **This is where I AM STUCK**
ind = new Array;
for(i=0; i<industries.length;i++){
ind[i] = new Array;
}
for(i=0;i<dataFetched.count;i++){
ind[i][0]= dataFetched.posts[i].categories[0].title;
for(j=0;j<dataFetched.count;j++){
var count = ind[i].length;
if(ind[i][0] == dataFetched.posts[j].categories[0].title){
ind[i][count] = dataFetched.posts[j].title;
}
}
}
It is possible to create object with categories. As a result all entries can be accessed by category name and you do not need to sort them to have unique titles:
var posts = dataFetched.posts;
var cat = {};
posts.forEach(
function(p) {
p.categories.forEach(
function(c) {
if (!cat[c.title])
cat[c.title] = [];
cat[c.title].push(p.title);
});
});
console.log(cat);
Output for your example:
Object {Law: Array[1], Business: Array[1], Technology: Array[2]}
Each category title is a key in this object and the arrays of posts are values of those keys.
The output example you showed is wrong, in JS there's no object like
[Category1: {Post_titleA, PostTitleB, PostTitleC}, Category2: {PostTileF, PostTileX}, etc ]
The most similar thing you can get is a JSON object like this:
{
"Category1" : ["Post_titleA", "PostTitleB", "PostTitleC"],
"Category2" : ["PostTileF", "PostTileX"],
//etc..
}
In order to achieve this, you can use the following function:
function getTitlesByCategory (json) {
var result = {}
json.posts.map(function (post) {
post.categories.map(function (category) {
result[category.title] = result[category.title] || [];
result[category.title].push(post.title);
});
});
return result;
}