Need to filter an JavaScript object - javascript

I need to filter an JS object as below format. I have some array of Object. every object contain title and data. I need to filter the object. title will not repet in object it will make an array of data and store every data in that.
Object
let results = [
{
"title": "exam",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},
{
"title": "prospectus",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},
{
"title": "prospectus",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "23",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},]
Filter object will be like this. title will not be repeated it will make an array.
"results": [
{
"title": "exam",
"data": {
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}
},
{
"title": "prospectus",
"data": [{
"status": "Active",
"studentId": "44",
"universityId": "0",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
},
{
"status": "Active",
"studentId": "44",
"universityId": "23",
"mediaId": "12",
"mediaName": "massey university",
"mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
"mediaDownload": 4
}]
I have tried this.
let filterData = [];
mainData.data.results.map((value) => {
if (filterData.length == 0) {
let obj = {
title: "title",
data: [{ ...value.data }],
};
filterData.push(obj);
} else {
let found = false;
}
});

This isn't really a filter operation, more of a reduce job where you want to collect data for the same title.
For that, I'd recommend creating a map of title to data
// this is just your data structure minified
const results = [{"title":"exam","data":{"status":"Active","studentId":"44","universityId":"0","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}},{"title":"prospectus","data":{"status":"Active","studentId":"44","universityId":"0","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}},{"title":"prospectus","data":{"status":"Active","studentId":"44","universityId":"23","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey%20university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}}];
// Collect data by title
const collect = results.reduce(
(map, { title, data }) => ({
...map,
[title]: [...(map[title] ?? []), data],
}),
{}
);
// Convert the mapped object to an array of objects
// with `title` and `data` properties
const filterData = Object.entries(collect).map(([title, data]) => ({
title,
data,
}));
console.log(filterData);
.as-console-wrapper { max-height: 100% !important; }
This will always put data in an array which keeps your data-structure consistent. If you really want single-element arrays to be destructured, use this instead for the last part
const filterData = Object.entries(collect).map(([title, data]) => ({
title,
data: data.length === 1 ? data[0] : data,
}));

The main problem here is to remember which title already exists and reduce it to just one with the data of all the same titles.
The above solution is good but it has a complexity of O(n^2) because it performs two loops. One to reduce the elements into an array of { title: [datas]} objects and one to transform it into the desired output of the form [{title, datas},...].
Using this solution we can perform the process with a complexity of O(n), using a hash table (directory) structure to remember the titles and reduce only those that are repeated.
let filterData = []
let directory = {}
mainData.data.results.map( (obj) => {
if(directory[obj.title] === undefined) {
directory[obj.title] = filterData.length
filterData.push({title: obj.title, data: [obj.data] })
} else {
filterData[directory[obj.title]].data.push(obj.data)
}
})

var resultObj = {}
results.forEach((item)=>{
if(!resultObj[item.title]){
resultObj[item.title] = {
title:item.title,
data:[]
}
}
resultObj[item.title].data.push(item.data)
})
var finalResultList = Object.values(resultObj)
console.log(finalResultList)

Related

How do I set value of nested object to key of current object?

This array has the key to substitute with nested key of 'name'
const arr = ['status', 'user', ...] <-- This array contains key to be replaced with name
This is what my current response object is
[
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}
]
How do I modify the above array of objects to this below
[
{
"id": 11,
"location": "Mumbai",
"status": "NEW",
"user": "Rakesh"
}
]
can try below code
const keys = ['status', 'user']
let arr = [
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}
]
arr.map(a => keys.forEach(k => {
if(a[k] && a[k].name) a[k] = a[k].name
}));
console.log(arr);
I'd try this one:
const results = [
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}, {
"id": 12,
"location": "Helsinki",
"status": {
"name": "NEW"
},
"user": {
"name": "Samuli"
}
}
];
const flattenObject = ([key, value]) => ((typeof value === 'object') ? {[key] : value[Object.keys(value)[0]]} : {[key]: value});
const reduceToSingleObject = (acc, b) => ({...acc, ...b});
const actualResults = results.map((result) => Object.entries(result).map(flattenObject).reduce(reduceToSingleObject));
console.log(actualResults);
Explanation:
flattenObject is a function to flatten structure of object inside object. This only takes the first prop (without knowing the name of the key). If you, for some reason, would need to flatten several key-values, then it'd need whole different kind of helper function to sort that out.
reduceToSingleObject is a function to put all the key-value pairs into a single object. This could have been done already in flattenObject function, but for the clarity, I separated it to a normal map - reduce pattern.
actualResults is the outcome where we go through all the entries of your original results.

I would like to create a set of constants based on the result of a .map

I am currently iterating over a .map JSON result from an API, and creating constants for each individual result I'd like to use. I'd like to be able to automate this, as in for when the map detects the "name" key, it creates a constant called "index0Name", followed by the value of "name", or the "_text" key and its value.
Is this possible? Example returned JSON API info below
{
"_attributes": {
"key": "10811142-ce47-44ea-8bdc-5e9f1391f179",
"number": "5",
"type": "GT",
"title": "Title 1- Element Red.gtzip",
"shortTitle": "Title 1- Element Red.gtzip",
"state": "Paused",
"position": "0",
"duration": "0",
"loop": "False",
"selectedIndex": "0"
},
"_text": "Title 1- Element Red.gtzip",
"text": [
{
"_attributes": {
"index": "0",
"name": "Headline.Text"
},
"_text": "HEADLINE"
},
{
"_attributes": {
"index": "1",
"name": "Description.Text"
},
"_text": "Description"
}
],
"image": {
"_attributes": {
"index": "0",
"name": "Logo Image.Source"
},
"_text": "4b42ada2-8745-4744-8104-fa42c18b3d6b\\IMAGE1.gif"
}
}
Current code is:
const modifiedMap = mapResult[0];
let inputMap = [];
if (modifiedMap) {
inputMap = modifiedMap.map((input, i) => {
const title = input._attributes.title;
const state = input._attributes.state;
const number = input._attributes.number;
const type = input._attributes.type;
// React result in here
}
return inputMap
}
In the above code, where it manually sets the constant "title" based on what it finds at input._attributes.title, I would like the map to
Iterate over input._attributes
Create a constant based on what it finds (Title, state, number...)
Set the value of that constant based on the value it finds of the corresponding key
Any help is appreciated as always.

Need to make on object in Javascript based on an existing object which is efficient considering its performance

{
"name": "test name",
"description": "test desc",
"data_table_id": 3,
"column_0": {
"value": "1",
"label": "name"
},
"condition_0": {
"value": "101",
"label": "Is equal to"
},
"column_1": {
"value": "2",
"label": "age"
},
"condition_1": {
"value": "102",
"label": "Is less than"
}
}
I have the above object in JavaScript. From this object I need to create the following object. Need to find a way which is good from performance point of view. The below conditions array is based on the object starting with 'column_' in the above object.
For example: if there are column_0, column_1, column_2, the length of conditions array will be 3. These columns will be coming dynamically, can be from 0-n, n = any integer >= 0. (i.e. column_0 - column_n)
The same condition applies for condition_0, condition_1. Also, condition_0 is always associated with column_0, condition_1 is always associated with column_1 ans so on.
{
"name": "test name",
"description": "test desc",
"data_table_id": 3,
"conditions" : [
{
"column_id": 1, // column_0.value
"column_name": "name", // column_0.label
"condition_id": 101 // condition_0.value
},
{
"column_id": 2, // column_1.value
"column_name": "age", // column_1.label
"condition_id": 102 // condition_1.value
}
],
}
extract the conditions using ...rest, reduce the Object.entries , construct the data structure and push it to the resulting array, finally put everything back together :
const data = {
"name": "test name",
"description": "test desc",
"data_table_id": 3,
"column_0": {
"value": "1",
"label": "name"
},
"condition_0": {
"value": "101",
"label": "Is equal to"
},
"column_1": {
"value": "2",
"label": "age"
},
"condition_1": {
"value": "102",
"label": "Is less than"
}
}
const {
name,
description,
data_table_id,
...rest
} = data;
const conditions = Object.entries(rest).reduce((all, [key, obj]) => {
if (key.startsWith('condition')) {
const id = key.split('_')[1];
const condition = {
"column_id": rest[`column_${id}`].value,
"column_name": rest[`column_${id}`].label,
"condition_id": obj.value,
}
all.push(condition)
}
return all;
}, []);
const result = {
name,
description,
data_table_id,
conditions
}
console.log(result)

Generate specific object from array of object

I am having an array like,
var result = [
{
"sItem" : [
"Pizza Margherita","Pizza marinara"
],
"sImage" : [
"https://assets.marthastewart.com/styles/wmax-300/d31/pizza-margherita-0606-mla102155/pizza-margherita-0606-mla102155_vert.jpg","https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"
],
"nQuantity" : 1,
"eDeliveryStatus" : "n",
"nPrice" : 215,
"sReceiptId" : "pRjZpGzIDPpX",
}
];
wants to make Object like, I am running a loop through title array pushing data.
[
{
"title":"Pizza Margherita",
"subtitle":"Pizza Margherita",
"quantity":1,
"price":215,
"currency":"INR",
"image_url":"https://images.mcdelivery.co.in/hardcastle-restaurants-pvt-ltd/image/upload/q_auto:low,fl_lossy,w_300/v1484907263/Items/2754.png"
},
{
"title":"Pizza marinara",
"subtitle":"Pizza marinara",
"quantity":1,
"price":215,
"currency":"INR",
"image_url":"https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"
}
]
and this is how i am trying but failing :(,
result.forEach(el => {
el.sItem.forEach(el2 => {
elementRec.push({
"title": el2,
"subtitle": el2,
"quantity": el.nQuantity,
"price": el.nPrice,
"currency": "INR",
"image_url": el.sImage
})
});
})
I know this is wrong but new to Javascript.
You are almost there.
In you forEach, add an index parameter and use it to retrieve the right image from the sImage array :
el.sItem.forEach((el2, index) => {
elementRec.push({
"title": el2,
"subtitle": el2,
"quantity": el.nQuantity,
"price": el.nPrice,
"currency": "INR",
"image_url": el.sImage[index]
})
});
var result = [
{
"sItem" : [
"Pizza Margherita",
"Pizza marinara"
],
"sImage" : [
"https://assets.marthastewart.com/styles/wmax-300/d31/pizza-margherita-0606-mla102155/pizza-margherita-0606-mla102155_vert.jpg",
"https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"
],
"nQuantity" : 1,
"eDeliveryStatus" : "n",
"nPrice" : 215,
"sReceiptId" : "pRjZpGzIDPpX",
}
];
var elementRec = [];
result.forEach(el => {
el.sItem.forEach((el2, index) => {
elementRec.push({
"title": el2,
"subtitle": el2,
"quantity": el.nQuantity,
"price": el.nPrice,
"currency": "INR",
"image_url": el.sImage[index]
})
});
});
console.log(elementRec);
You could map the inner sItem and corresponding sImage to new object by some destruction and short properties.
var data = [{ sItem: ["Pizza Margherita", "Pizza marinara"], sImage: ["https://assets.marthastewart.com/styles/wmax-300/d31/pizza-margherita-0606-mla102155/pizza-margherita-0606-mla102155_vert.jpg", "https://www.silviocicchi.com/pizzachef/wp-content/uploads/2015/02/m-evid-672x372.jpg"], nQuantity: 1, eDeliveryStatus: "n", nPrice: 215, sReceiptId: "pRjZpGzIDPpX" }],
result = data.reduce((r, { sItem, sImage, nQuantity: quantity, nPrice: price }) =>
r.concat(sItem.map((title, i) => ({
title, subTitle: title, quantity, price, currency: 'INR', image_url: sImage[i]
}))),
[]
);
console.log(result);
I think you are trying to do something like this. First create a new array. I'll call it converted. Then push the result objects into it with .forEach() like this.
var converted = [];
result.forEach(function(i){
converted.push({
"title": i.sItem[0],
"subtitle": i.sItem[0],
"quantity": i.nQuantity,
"price": i.nPrice,
"currency": "INR",
"image_url": i.sImage[0]
});
})
Try this fiddle

Filter out unique value from object inside array using loadsh

I am trying to get the unique category from the following array using loadsh,
[{
"listingId": "p106a904a-b8c6-4d2d-a364-0d21e3505010",
"section": "section1",
"category": "VIP PASS ",
"type": "paper",
"availableTickets": 1
}, {
"listingId": "p106904a-b8c6-4d2d-a364-0d21e3505010",
"section": "section1",
"category": "VIP PASS ",
"type": "paper",
"availableTickets": 2
}, {
"listingId": "pc8f54389-4e58-482a-9535-6917c2948764",
"section": "1",
"category": "WIP",
"type": "paper",
"availableTickets": 1
}]
This is what i have tried
this.categories = _.uniq(this.listings, function (test: ListDAO) { return test.category; });
but the above returns the same array again. how can i get the output result as,
VIP PASS and WIP
Without lodash and using .reduce:
let arr2 = arr.reduce((a, i) => a.indexOf(i.category) > -1 ? a : a.concat(i.category), []);
https://jsfiddle.net/42my6p08/
You need to use uniqBy as uniq only accepts a regular array with no callback for each.
https://lodash.com/docs/4.17.4#uniqBy
You can try this:
this.categories = _.uniqBy(this.listings, ({ category }) => category);
If you want just the strings (as per comments) you can just do:
const getCategory = ({ category }) => category;
this.categories = _.uniqBy(this.listings, getCategory).map(getCategory);
(can also use the same callback function from your OP instead of mine.)
A solution using Map and reduce.
var arr = [{
"listingId": "p106a904a-b8c6-4d2d-a364-0d21e3505010",
"section": "section1",
"category": "VIP PASS ",
"type": "paper",
"availableTickets": 1
}, {
"listingId": "p106904a-b8c6-4d2d-a364-0d21e3505010",
"section": "section1",
"category": "VIP PASS ",
"type": "paper",
"availableTickets": 2
}, {
"listingId": "pc8f54389-4e58-482a-9535-6917c2948764",
"section": "1",
"category": "WIP",
"type": "paper",
"availableTickets": 1
}];
var unique = arr.reduce((map, o) => (map.has(o.category) ? map : map.set(o.category)),new Map());
console.log(Array.from(unique.keys()));

Categories