How to customize sort objects by property? - javascript

Starting with a given array of objects, I group those by their classification property into an object keyed by that classification. Then I print out the desired classification effect.
Now I need to sort these classifications. I want the commonly used ones to be printed first, and other classifications to be sorted alphabetically after it.
So I hope the sorting effect is as follows:
common used is the first
others are alphabetic
Here is the expected structure, the actual results in the code run
commonly-used
stackoverflow
github
movie-type
movie site
movie site2
search-type
google
wikipedia
study-type
w3c
vue
react
tool-type
remove bg
Here is my code where the grouping is done, but where I still need to add the sorting somehow:
let ary = [{
"type": "search-type",
"content": {
"title": "google",
"link": "https://",
}
}, {
"type": "study-type",
"content": {
"title": "w3c",
"link": "https://",
}
}, {
"type": "movie-type",
"content": {
"title": "movie site",
"link": "https://",
}
}, {
"type": "commonly-used",
"content": {
"title": "stackoverflow",
"link": "https://",
}
}, {
"type": "tool-type",
"content": {
"title": "remove bg",
"link": "https://www//",
}
}, {
"type": "movie-type",
"content": {
"title": "movie site2",
"link": "https://",
}
}, {
"type": "commonly-used",
"content": {
"title": "github",
"link": "https://",
}
}, {
"type": "search-type",
"content": {
"title": "wikipedia",
"link": "https://xx",
}
}, {
"type": "study-type",
"content": {
"title": "vue",
"link": "https://",
}
}, {
"type": "study-type",
"content": {
"title": "react",
"link": "https://",
}
}];
////////////////////
let tempJson = {};
ary.forEach(data => tempJson[data.type] = [])
ary.forEach(data => {
for (const key in tempJson) {
if (data.type === key) {
tempJson[key].push(data.content);
break;
}
}
})
for (const classification in tempJson) {
const wrapNode = `<div class="item-wrap">
<h3>${classification}</h3>
${(() => {
let contentWrapNode = ``;
tempJson[classification].forEach(item => {
const itemNode = `<div class="items">${item.title}</div>`;
contentWrapNode += itemNode;
})
return contentWrapNode;
})()}
</div>`;
document.querySelector('.container').innerHTML += wrapNode;
}
<div class="container"></div>
The data obtained are without order. I just classify them. How should they be sorted?

You can get a sorted version of tempJson by first extracting the key value pairs from it, and then sorting it with a callback function that deals with "commonly-used" separately:
let ary = [{
"type": "search-type",
"content": {
"title": "google",
"link": "https://",
}
}, {
"type": "study-type",
"content": {
"title": "w3c",
"link": "https://",
}
}, {
"type": "movie-type",
"content": {
"title": "movie site",
"link": "https://",
}
}, {
"type": "commonly-used",
"content": {
"title": "stackoverflow",
"link": "https://",
}
}, {
"type": "tool-type",
"content": {
"title": "remove bg",
"link": "https://www//",
}
}, {
"type": "movie-type",
"content": {
"title": "movie site2",
"link": "https://",
}
}, {
"type": "commonly-used",
"content": {
"title": "github",
"link": "https://",
}
}, {
"type": "search-type",
"content": {
"title": "wikipedia",
"link": "https://xx",
}
}, {
"type": "study-type",
"content": {
"title": "vue",
"link": "https://",
}
}, {
"type": "study-type",
"content": {
"title": "react",
"link": "https://",
}
}];
////////////////////
let tempJson = {};
ary.forEach(data => tempJson[data.type] = [])
ary.forEach(data => {
for (const key in tempJson) {
if (data.type === key) {
tempJson[key].push(data.content);
break;
}
}
})
let sorted = Object.entries(tempJson).sort(([a], [b]) =>
(a != "commonly-used") - (b != "commonly-used") ||
a.localeCompare(b)
);
for (const [classification, items] of sorted) {
const wrapNode = `<div class="item-wrap">
<h3>${classification}</h3>
${(() => {
let contentWrapNode = ``;
items.forEach(item => {
const itemNode = `<div class="items">${item.title}</div>`;
contentWrapNode += itemNode;
})
return contentWrapNode;
})()}
</div>`;
document.querySelector('.container').innerHTML += wrapNode;
}
<div class="container"></div>

Related

How to customize sort an array

I'm trying to sort an array of objects in JS, but it doesn't work for some reason.
The array I requested from API may contain numbers, upper and lower case letters, and some Chinese characters.
eg:
const arr = [
{ "title": "!Test Segment and CSV" },
{ "title": "&test (SC)" },
{ "title": "1234test (SC)" },
{ "title": "AAShop1 (SC)" },
{ "title": "AAShop2(SC)" },
{ "title": "ABCshop123 (SC)" },
{ "title": "adidas Outlet" },
{ "title": "AIGLE" },
{ "title": "American Eagle" },
{ "title": "Châteraisé" },
{ "title": "Tekcent" },
{ "title": "반찬 & COOK" },
{ "title": "始祖鸟" },
{ "title": "春水堂" },
{ "title": "稻成" }
];
I want it sorted according to the following rules.
sort a after A
sort B after A
sort Ac after ABC
{ "title": "!Test Segment and CSV" },
{ "title": "&test (SC)" },
{ "title": "1234test (SC)" },
{ "title": "AAShop1 (SC)" },
{ "title": "AAShop2(SC)" },
{ "title": "ABCshop123 (SC)" },
{ "title": "AIGLE" },
{ "title": "American Eagle" },
{ "title": "adidas Outlet" },
{ "title": "Châteraisé" },
{ "title": "Tekcent" },
{ "title": "始祖鸟" },
{ "title": "春水堂" },
{ "title": "稻成" },
{ "title": "반찬 & COOK" }
Thanks in advance for any help!
.sort() and .localeCompare(). Note, in the OP, the input array is already sorted correctly so in this answer I have jumbled the order of the input array to demonstrate that the code functions correctly.
const data = [{ "title": "BB" }, { "title": "Ac" }, { "title": "adidas" }, { "title": "AA" }, { "title": "Ba" }, { "title": "ABC" }];
const output = data.sort((a, b) => a.title.localeCompare(b.title));
console.log(output);
You just need to sort it on lower case.
let myArr = [{ "title": "AA" }, { "title": "ABC" }, { "title": "Ac" }, { "title": "adidas" }, { "title": "Ba" }, { "title": "BB" }]
let sortList = myArr.sort(function (a, b) {
return a.title.toLowerCase() > b.title.toLowerCase()
})
console.log(sortList)
You can simply achieve that without manipulating a string into a lowerCase with the only help of a simple Array.sort() method.
Live Demo :
let myArr = [{ "title": "AA" }, { "title": "ABC" }, { "title": "Ac" }, { "title": "adidas" }, { "title": "Ba" }, { "title": "BB" }];
let sortedArr = myArr.sort((a, b) => {
return a.title - b.title
});
console.log(sortedArr);

Filter an array of objects with nested arrays based on another array

I've 2 different APIs. first one returns an array of event objects (this data set is growing and expected to be large). each event has a category array that has a list of strings. The other API returns an array of filter objects. each filter has a "name" property and an array of keywords. any keyword included in the categories array in any event should go under this filter name.
The ultimate goal is to have a list of filters on the screen and when a user click on a filter I should render all events under this filter.
Event Object Example:
{
"text": {
"headline": "Headline example",
"text": "event description "
},
"media": {
"url": "https://www.google.com/",
"caption": "",
"credit": ""
},
"categories": [
"National",
"Canada",
"British Columbia"
]
}
Filters Object Example:
{
"filters": [
{
"keywords": [
"Atlantic",
"New Brunswick",
"Newfoundland and Labrador",
"Prince Edward Island",
"Nova Scotia"
],
"name": "Atlantic"
},
{
"keywords": [
"ontario",
"Quebec"
],
"name": "Central Canada"
},
{
"keywords": [
"Manitoba",
"Saskatchewan",
"Alberta"
],
"name": "Prairie Provinces"
},
{
"keywords": [
"British Columbia"
],
"name": "West Coast"
},
{
"keywords": [
"Nunavut",
"Northwest Territories",
"Yukon Territory"
],
"name": "North"
},
{
"keywords": [
"National"
],
"name": "National"
}
]
}
After a couple of days working on it I came up with this solution.
function filterTimelineData(filtersObj, timelineData) {
if (!timelineData || !filtersObj) return [];
// create a new object with filters "name" as key;
const filters = Object.keys(filtersObj);
const filteredTimelineData = Object.keys(filtersObj).reduce((o, key) => ({ ...o, [key]: [] }), {});
const filteredData = timelineData.events.reduce((acc, current) => {
let filterMatch = false;
let filterMatchName = '';
for (let i = 0; i < filters.length; i++) {
filterMatch = current.categories.some(item => {
return filtersObj[filters[i]].includes(item.toLocaleLowerCase());
});
if (filterMatch && filterMatchName !== filters[i]) { // to avoid duplicated items with different categories under the same filter
filterMatchName = filters[i];
acc[filters[i]].push(current);
}
}
return acc;
}, filteredTimelineData);
return filteredData;
}
export function timelineFiltersObj(filters) {
const filtersObj = filters.filters.reduce((acc, current) => {
const filterName = current.name.replace(/ /g, '_').toLocaleLowerCase();
if (!acc.hasOwnProperty(filterName)) {
acc[filterName] = [];
}
acc[filterName] = [].concat(current.keywords.map(item => item.toLocaleLowerCase()));
return acc;
}, {});
return filtersObj;
}
Desired output:
An object or an array for all filters to be rendered on the screen
An object with filters name as a key and the value would be an array of events that has any keyword that matches any of this filter keywords
check this code example: link
My Questions:
Is there an easier/simpler way to solve this problem?
I'm passing "filteredTimelineData" object as initial value to .reduce function. Is this legitimate? I couldn't find any answers online to this question specifically.
from a time complexity prospective. will this code cause any memory issue if the dataset grows?
This is a simple way to get the above result. I am using JavaScript ES5 features in this solution which is supported by almost all the browsers except IE9
const filters = {
"filters": [
{
"keywords": [
"Atlantic",
"New Brunswick",
"Newfoundland and Labrador",
"Prince Edward Island",
"Nova Scotia"
],
"name": "Atlantic"
},
{
"keywords": [
"ontario",
"Quebec"
],
"name": "Central Canada"
},
{
"keywords": [
"Manitoba",
"Saskatchewan",
"Alberta"
],
"name": "Prairie Provinces"
},
{
"keywords": [
"British Columbia"
],
"name": "West Coast"
},
{
"keywords": [
"Nunavut",
"Northwest Territories",
"Yukon Territory"
],
"name": "North"
},
{
"keywords": [
"National"
],
"name": "National"
}
]
};
const timelineData = {
"events": [
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"New Brunswick"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": "https://youtu.be/poOO4GN3TN4"
},
"categories": [
"Northwest Territories"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"Ontario"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": "https://philanthropy.cdn.redcross.ca/timeline/July2020-3.jpg"
},
"categories": [
"British Columbia"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"Alberta"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"Prince Edward Island"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
},
{
"text": {
"headline": "headline example",
"text": "event-descriprion"
},
"media": {
"url": ""
},
"categories": [
"National"
]
}
]
};
var categoriesToEventsMap = timelineData.events.reduce((res, event) => {
event.categories.forEach(c=> {
res = {
...res,
[c.toLowerCase()]: [...(res[c.toLowerCase()] || []), event]
}
});
return res;
}, {})
var result = filters.filters.reduce((acc, filter) => {
let events = []
const filterName = filter.name.replace(' ', '_').toLowerCase();
filter.keywords.forEach((key)=>{
events = [...events, ...(categoriesToEventsMap[key.toLowerCase()] || [])];
});
acc[filterName] = [...(acc[filterName] || []), ...events]
return acc;
}, {});
console.log(result);

Flatten arrays within object of arrays with data from parent object

I want to flatten some arrays nested in each object of an array of objects to return an array of objects with data from the parent objects. Quite a mouthful but perhaps some example json will help explain.
My current data and code is:
const galleries = [
{
"gallery": [
{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
}
],
"slug": "stella-mccartney",
"title": "Stella McCartney"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
}
],
"slug": "esquire",
"title": "Esquire"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
}
],
"slug": "matches",
"title": "Matches"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
}
],
"slug": "testing-project-2",
"title": "Testing Project 2"
}
]
const AllThumbnails = [].concat(
...galleries.map((gallery) => ({
image: gallery.gallery,
slug: gallery.slug,
}))
)
console.log(AllThumbnails)
My ideal output is:
[
{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg",
"slug": "stella-mccartney"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg",
"slug": "stella-mccartney"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg",
"slug": "stella-mccartney"
},
{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg",
"slug": "esquire"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg",
"slug": "esquire"
},
{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg",
"slug": "matches"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg",
"slug": "matches"
},
{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg",
"slug": "testing-project-2",
}
]
How can I append the slug property correctly? Any help/pointers would be much appreciated.
You could use
const allThumbnails = galleries.map(parent =>
parent.gallery.map(g => ({url: g.url, slug: parent.slug}))).flat();
.map() will map each parent object to an array of {url, slug}, and then .flat() will flatten these nested arrays.
const galleries = [
{
"gallery": [
{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
}
],
"slug": "stella-mccartney",
"title": "Stella McCartney"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
}
],
"slug": "esquire",
"title": "Esquire"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
}
],
"slug": "matches",
"title": "Matches"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
}
],
"slug": "testing-project-2",
"title": "Testing Project 2"
}
];
const allThumbnails = galleries.map(parent => parent.gallery.map(g => ({url: g.url, slug: parent.slug}))).flat();
console.log(allThumbnails);
you can use reduce to do this
const galleries = [{
"gallery": [{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
}
],
"slug": "stella-mccartney",
"title": "Stella McCartney"
},
{
"gallery": [{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
}
],
"slug": "esquire",
"title": "Esquire"
},
{
"gallery": [{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
}
],
"slug": "matches",
"title": "Matches"
},
{
"gallery": [{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
}],
"slug": "testing-project-2",
"title": "Testing Project 2"
}
]
const flatten = galleries.reduce((acc, curr) => {
curr.gallery.forEach(g => {
acc.push({
url: g.url,
slug: curr.slug
});
});
return acc;
}, []);
console.log(flatten);
Looks like I'm a little late with my answer, I think Kirill's solution is going to be the most practical one.
Here is my solution anyways:
let newArray = []
galleries.forEach(function (gallery) {
gallery["gallery"].forEach(function (url) {
newArray.push({"url": url["url"], "slug": gallery["slug"]})
})
})
Some of these answers are very close to mine, but here's mine using forEach with ES6 syntax, which in my opinion is more readable:
const allThumbnails = new Array();
thumbnails.forEach(set => {
set.galleries.forEach(item => {
allThumbnails.push({url: item.url, slug: set.slug};
});
});

Iterate and group the objects using map function

Check for the decimal id and group them accordingly.
Below are the sample and recommended JSON's
Sample JSON
{
"results": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
}
Would like to iterate and Re-structure the above JSON into below recommended format.
Logic: Should check the id(with and without decimals) and group them based on the number.
For Example:
1, 1.1, 1.2.3, 1.4.5 => data1: [{id: 1},{id: 1.1}....]
2, 2.3, 2.3.4 => data2: [{id: 2},{id: 2.3}....]
3, 3.1 => data3: [{id: 3},{id: 3.1}]
Recommended JSON
{
"results": [
{
"data1": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
}
]
},
{
"data2": [
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
}
]
},
{
"data3": [
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
}
]
},
{
"data4": [
{
"name": "Download",
"id": "4.2"
}
]
}
]
}
I have tried the below solution but it doesn't group the object
var formatedJSON = [];
results.map(function(d,i) {
formatedJSON.push({
[data+i]: d
})
});
Thanks in advance.
You can use reduce like this. The idea is to create a key-value pair for each data1, data2 etc so that values in this object are the values you need in the final array. Then use Object.values to get those as an array.
const sampleJson = {"results":[{"name":"Download","id":"1.1.1"},{"name":"Download","id":"1.2"},{"name":"Download","id":"1.3.2"},{"name":"Download","id":"2"},{"name":"Download","id":"2.3"},{"name":"Download","id":"3.2"},{"name":"Download","id":"3.5"},{"name":"Download","id":"4.2"}]}
const grouped = sampleJson.results.reduce((a, v) => {
const key = `data${parseInt(v.id)}`;
(a[key] = a[key] || {[key]: []})[key].push(v);
return a;
},{});
console.log({results: Object.values(grouped)})
One liner / Code-golf:
let s={"results":[{"name":"Download","id":"1.1.1"},{"name":"Download","id":"1.2"},{"name":"Download","id":"1.3.2"},{"name":"Download","id":"2"},{"name":"Download","id":"2.3"},{"name":"Download","id":"3.2"},{"name":"Download","id":"3.5"},{"name":"Download","id":"4.2"}]},k;
console.log({results:Object.values(s.results.reduce((a,v)=>(k=`data${parseInt(v.id)}`,(a[k] = a[k]||{[k]:[]})[k].push(v),a),{}))})
Here you go:
var data = {
"results": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
};
let newSet = new Set();
data.results.forEach(e => {
let key = e.id.substring(0, e.id.indexOf('.'));
console.log(key);
if (newSet.has(key) == false) {
newSet.add(key);
newSet[key] = [];
}
newSet[key].push(e.id);
});
console.log(newSet);
Here's how you'd do it:
var data = {
"results": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
};
var newData = {
"results": {}
};
data.results.forEach(item => {
var num = item.id.slice(0, 1);
if (newData.results["data" + num]) {
newData.results["data" + num].push(item);
} else {
newData.results["data" + num] = [item];
}
})
data = newData;
console.log(data);
What this does is it iterates through each item in results, gets the number at the front of this item's id, and checks if an array of the name data-{num} exists. If the array exists, it's pushed. If it doesn't exist, it's created with the item.
let input = getInput();
let output = input.reduce((acc, curr)=>{
let {id} = curr;
let majorVersion = 'name' + id.split('.')[0];
if(!acc[majorVersion]) acc[majorVersion]= [];
acc[majorVersion].push(curr);
return acc;
},{})
console.log(output)
function getInput(){
return [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
}
One solution with RegEx for finer control as it would differentiate easily between 1 and 11.
Also this will make sure that even if the same version comes in end(say 1.9 in end) it will put it back in data1.
let newArr2 = ({ results }) =>
results.reduce((acc, item) => {
let key = "data" + /^(\d+)\.?.*/.exec(item.id)[1];
let found = acc.find(i => key in i);
found ? found[key].push(item) : acc.push({ [key]: [item] });
return acc;
}, []);

Fetch only specific objects from JSON via javascript or jQuery

I would like to fetch only specific objects from the below JSON such as only those JSON objects which have a classDefinition = "com.sap.bpm.wfs.UserTask". Please suggest on how to do this:
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
"id": "startevent1",
"name": "StartEvent1"
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
"id": "endevent1",
"name": "EndEvent1"
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
"id": "sequenceflow1",
"name": "SequenceFlow1",
"sourceRef": "83eaead8-cfae-459b-9bdd-8b12e32d6715",
"targetRef": "6c2b0935-444b-4299-ac8e-92973ce93558"
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
"symbols": {
"760f0725-3400-4d48-b082-5c69ad79d697": {},
"aa9a0d10-63be-4af8-9ac2-4d2b648a18fc": {},
"7fbd11bb-cf82-4a27-97d7-e80dda2014ee": {},
"20c66c48-6058-465e-b500-d69d6e54c028": {},
"2e8f324c-5361-4512-a09a-fc7693f206ba": {}
}
}
}
};
First, metadata.contents property should rather be an array.
If you really cannot change it to an array, then use Object.keys(metadata.contents)
For example:
Object.keys(metadata.contents)
.map(x => metadata.contents[x])
.filter(x => x.classDefinition == 'com.sap.bpm.wfs.UserTask')
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
}
}
}
var filtered = Object.keys(metadata.contents)
.map(x => metadata.contents[x])
.filter(x => x.classDefinition == 'com.sap.bpm.wfs.UserTask')
console.log(filtered)
A simple for loop can be used to get the desired fields:
var temp = [];
for (var index in metadata.contents) {
if (metadata.contents[index].classDefinition == "com.sap.bpm.wfs.UserTask") {
temp.push(metadata.contents[index]);
}
}
Or you can do one by one
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
"id": "startevent1",
"name": "StartEvent1"
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
"id": "endevent1",
"name": "EndEvent1"
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
"id": "sequenceflow1",
"name": "SequenceFlow1",
"sourceRef": "83eaead8-cfae-459b-9bdd-8b12e32d6715",
"targetRef": "6c2b0935-444b-4299-ac8e-92973ce93558"
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
"symbols": {
"760f0725-3400-4d48-b082-5c69ad79d697": {},
"aa9a0d10-63be-4af8-9ac2-4d2b648a18fc": {},
"7fbd11bb-cf82-4a27-97d7-e80dda2014ee": {},
"20c66c48-6058-465e-b500-d69d6e54c028": {},
"2e8f324c-5361-4512-a09a-fc7693f206ba": {}
}
}
}
}
var content = metadata["contents"];
var subContent = content["6c2b0935-444b-4299-ac8e-92973ce93558"];
var classDef = subContent["classDefinition"];
alert(classDef);

Categories