I need to sort an array in javascript - javascript

I am getting json data like this
[
{
"emission": [
{
"id": "fffda276-c7ed-4931-8211-48b3ae304b6f",
"size": "Medium",
}
],
"id": "db9dd205-5986-432f-9aaf-1079d6fdd28c",
},
{
"emission": [
{
"id": "5ae8991c-bbcd-4a97-a5ad-b1aac6d765c0",
"size": "",
},
{
"id": "f670609a-d200-4c03-a8a7-34e2b244a4c7",
"size": "Small",
}
],
"id": "95a9c2eb-7dac-45d6-9a6a-2718859d91f3",
},
{
"emission": [
{
"id": "77f5b953-772a-4e02-834f-6d7eb4236223",
"size": "Medium",
},
{
"id": "04e909bc-0087-479d-9f4d-8f4ad03f8dd0",
"size": "Large",
},
{
"id": "4a628027-3ec8-450c-943e-7dce96f0bbb4",
"size": "Small",
},
{
"id": "7c5c638b-bab6-4a10-ba3e-ebdc8939021d",
"size": "Large",
}
],
"id": "bc38b226-78cd-4928-80a0-589a9da2cd40",
},
{
"emission": [
{
"id": "e6011db7-0662-4b52-9d26-e6be07226826",
"size": "Large",
},
{
"id": "ad678447-3e18-4537-baa1-b762dc03f6cd",
"size": "Medium",
}
],
"id": "e1c59ebd-b567-462f-ac00-068ff7938055",
},
{
"emission": [
{
"id": "3525d215-e9eb-4417-8b35-902936181d29",
"size": "Medium",
},
{
"id": "4c023985-a3c0-4783-a9c3-d51a21bf63d9",
"size": "Large",
},
{
"id": "7ef8d908-8a29-4d40-bdfe-121895d01ebc",
"size": "Medium",
}
],
"id": "d9e88ddc-1b7e-4a68-b087-46d365f266a3",
}
]
I need to reorder entire data based on emission array's size like large, medium and small, so that first array must be no of count of Large, then medium and small, it needs to be sorted
Note: some data can also be without size those data can be omitted, but still needs to be present in final sorted array
Output:
[
{
"emission": [
{
"id": "77f5b953-772a-4e02-834f-6d7eb4236223",
"size": "Medium",
},
{
"id": "04e909bc-0087-479d-9f4d-8f4ad03f8dd0",
"size": "Large",
},
{
"id": "4a628027-3ec8-450c-943e-7dce96f0bbb4",
"size": "Small",
},
{
"id": "7c5c638b-bab6-4a10-ba3e-ebdc8939021d",
"size": "Large",
}
],
"id": "bc38b226-78cd-4928-80a0-589a9da2cd40",
},
{
"emission": [
{
"id": "3525d215-e9eb-4417-8b35-902936181d29",
"size": "Medium",
},
{
"id": "4c023985-a3c0-4783-a9c3-d51a21bf63d9",
"size": "Large",
},
{
"id": "7ef8d908-8a29-4d40-bdfe-121895d01ebc",
"size": "Medium",
}
],
"id": "d9e88ddc-1b7e-4a68-b087-46d365f266a3",
},
{
"emission": [
{
"id": "e6011db7-0662-4b52-9d26-e6be07226826",
"size": "Large",
},
{
"id": "ad678447-3e18-4537-baa1-b762dc03f6cd",
"size": "Medium",
}
],
"id": "e1c59ebd-b567-462f-ac00-068ff7938055",
},
{
"emission": [
{
"id": "fffda276-c7ed-4931-8211-48b3ae304b6f",
"size": "Medium",
}
],
"id": "db9dd205-5986-432f-9aaf-1079d6fdd28c",
},
{
"emission": [
{
"id": "5ae8991c-bbcd-4a97-a5ad-b1aac6d765c0",
"size": "",
},
{
"id": "f670609a-d200-4c03-a8a7-34e2b244a4c7",
"size": "Small",
}
],
"id": "95a9c2eb-7dac-45d6-9a6a-2718859d91f3",
}
]

You could count wanted type and sort descending.
const
count = ({ emission }, type) =>
emission.reduce((r, { size }) => r + (type === size), 0),
data = [{ emission: [{ id: "fffda276-c7ed-4931-8211-48b3ae304b6f", size: "Medium" }], id: "db9dd205-5986-432f-9aaf-1079d6fdd28c" }, { emission: [{ id: "5ae8991c-bbcd-4a97-a5ad-b1aac6d765c0", size: "" }, { id: "f670609a-d200-4c03-a8a7-34e2b244a4c7", size: "Small" }], id: "95a9c2eb-7dac-45d6-9a6a-2718859d91f3" }, { emission: [{ id: "77f5b953-772a-4e02-834f-6d7eb4236223", size: "Medium" }, { id: "04e909bc-0087-479d-9f4d-8f4ad03f8dd0", size: "Large" }, { id: "4a628027-3ec8-450c-943e-7dce96f0bbb4", size: "Small" }, { id: "7c5c638b-bab6-4a10-ba3e-ebdc8939021d", size: "Large" }], id: "bc38b226-78cd-4928-80a0-589a9da2cd40" }, { emission: [{ id: "e6011db7-0662-4b52-9d26-e6be07226826", size: "Large" }, { id: "ad678447-3e18-4537-baa1-b762dc03f6cd", size: "Medium" }], id: "e1c59ebd-b567-462f-ac00-068ff7938055" }, { emission: [{ id: "3525d215-e9eb-4417-8b35-902936181d29", size: "Medium" }, { id: "4c023985-a3c0-4783-a9c3-d51a21bf63d9", size: "Large" }, { id: "7ef8d908-8a29-4d40-bdfe-121895d01ebc", size: "Medium" }], id: "d9e88ddc-1b7e-4a68-b087-46d365f266a3" }];
data.sort((a, b) =>
count(b, 'Large') - count(a, 'Large') ||
count(b, 'Medium') - count(a, 'Medium') ||
count(b, 'Small') - count(a, 'Small')
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

I couldn't fully understand what you meant, but I assume a sorting by Large, Medium and Small might help you
let data = [
{
"emission": [
{
"id": "fffda276-c7ed-4931-8211-48b3ae304b6f",
"size": "Medium",
}
],
"id": "db9dd205-5986-432f-9aaf-1079d6fdd28c",
},
// ... other data objects
];
let sortedData = data.sort((a, b) => {
let aCount = countSizes(a.emission, 'Large');
let bCount = countSizes(b.emission, 'Large');
if (aCount !== bCount) {
return bCount - aCount;
}
aCount = countSizes(a.emission, 'Medium');
bCount = countSizes(b.emission, 'Medium');
if (aCount !== bCount) {
return bCount - aCount;
}
aCount = countSizes(a.emission, 'Small');
bCount = countSizes(b.emission, 'Small');
return bCount - aCount;
});
function countSizes(emission, size) {
return emission.filter(e => e.size === size).length;
}
console.log(sortedData);
Explanation:
In the code, the countSizes function is used to count the number of occurrences of a specific size in the emission array. The sort method is used to sort the data array based on the number of occurrences of Large, Medium, and Small sizes, in that order. The resulting sortedData array will have the data objects ordered based on the number of occurrences of the sizes in the emission array.

Related

nest items in JSON based on value?

Trying to get my head around this one..
Incoming data looks like:
[
{
"value": {
"label": "MZ Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Lionel Carter"
}
},
{
"value": {
"label": "BW Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Jerome Yost"
}
},
{
"value": {
"label": "Detergent",
"type": "case",
"incident": null,
"personName": "Jerald Legros"
}
}
]
I would like to transform this into
[
{
"label": "Algal bloom",
"children": [
{ "label": "Lionel Carter", "type": "case"},
{ "label": "Jerome Yost", "type": "case" }]
},
{ "label": "Detergent", "type": "case" }
]
Basically, the rule is that if incident is not NULL then the incident name becomes the parent and the children hold the personName - otherwise we simply pass through the label and type. I can walk the array and switch out the label with the incident name, but I'm not sure how to group up the incidents..
It's basic grouping with an exception for elements without incident.
You can group the elements without incident in a separate group:
const data = [{"value": {"label": "MZ Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Lionel Carter"}},{"value": {"label": "BW Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Jerome Yost"}},{"value": {"label": "Detergent","type": "case","incident": null,"personName": "Jerald Legros"}}];
function group(data) {
const result = data.reduce((acc, { value }) => {
if (!value.incident) {
acc.ungrouped.push({ label: value.label, type: value.type });
} else {
if (!acc.groups[value.incident.name]) acc.groups[value.incident.name] = { label: value.incident.name, children: [] };
acc.groups[value.incident.name].children.push({ label: value.personName, type: value.type });
}
return acc;
}, { groups: {}, ungrouped: [] });
return [...Object.values(result.groups), ...result.ungrouped];
}
console.log(group(data));

Creating an object which contains unique item from a nested array

I have an array of objects called employees. I need a solution that will return me a list of groups and respective employees present in the group along with the group properties.
The example is below, I have used an object but the result can also be an array that has a property called groupName within an object. [{groupName:"developer", employees:[],...}..] As long as the response returns a list of groups with their corresponding employees.
Below is the solution I did but I need a solution with a better time complexity that is O(n).
const employees = [
{ "name": "John Doe",
"id": "1",
"groups": [
{ "id": "developerId", "name": "developer", "color": "#fff" },
{ "id": "engineerId", "name": "engineer", "color": "#fff" }
],
"groupId":["developerId", "engineerId"]
},
{ "name": "Jane Doe",
"id": "2",
"groups": [
{ "id": "developerId", "name": "developer", "color": "#fff" },
{ "id": "testerId", "name": "tester", "color": "#fff" }
],
"groupId":["developerId", "testerId"]
}
]
//Solution O(m*n)
let groups = {};
employees.forEach((item) => {
item.groups.forEach((group) => {
if (!groups[group.name]) {
groups[group.name] = {
employees: [item.id],
...group,
};
} else {
groups[group.name].employees = [...groups[group.name].employees, item.id];
}
});
});
//result
{
"developer":{
"id":"developerId",
"employee":[
"1",
"2"
],
"color":"#fff"
},
"engineer":{
"id":"employeeId",
"employee":[
"1",
],
"color":"#fff"
},
"tester":{
"id":"testerId",
"employee":[
"2",
],
"color":"#fff"
}
}
Using Array#reduce and Array#forEach:
const employees = [
{
"name": "John Doe",
"id": "1",
"groups": [
{ "id": "developerId", "name": "developer", "color": "#fff" },
{ "id": "engineerId", "name": "engineer", "color": "#fff" }
],
"groupId": ["developerId", "engineerId"]
},
{
"name": "Jane Doe",
"id": "2",
"groups": [
{ "id": "developerId", "name": "developer", "color": "#fff" },
{ "id": "testerId", "name": "tester", "color": "#fff" }
],
"groupId": ["developerId", "testerId"]
}
];
const groups = employees.reduce((acc, { id: employeeId, groups = [] }) => {
groups.forEach(({ id, name, color }) => {
acc[name] = {
id, color, employee: [...(acc[name]?.employee ?? []), employeeId]
};
});
return acc;
}, {});
console.log(groups);
If you like to add some speed, you could use the old fashioned for statement for iterating, especially of having only a single result object.
This approach does not create an object again and again and uses the already existing objects.
const
employees = [{ name: "John Doe", id: "1", groups: [{ id: "developerId", name: "developer", color: "#fff" }, { id: "engineerId", name: "engineer", color: "#fff" }], groupId: ["developerId", "engineerId"] }, { name: "Jane Doe", id: "2", groups: [{ id: "developerId", name: "developer", color: "#fff" }, { id: "testerId", name: "tester", color: "#fff" }], groupId: ["developerId", "testerId"] }],
result = {};
for (const { id: employeeId, groups } of employees) {
for (const { id, name, color } of groups) {
result[name] ??= { id, color, employee: [] };
result[name].employee.push(employeeId);
}
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

TypeScript / JS -- sort an array of nested objects based on a property common to all objects

I'm learning TypeScript and JS and struggling to solve multiple problems. One of them is this, that I have at hand. Say, I have an array of Application objects. Each Application object has this kind of a nested structure:
Application
|
----[Document Type]
---------|
--------------[Document]
------------------|
------------------------Metadata
(Each Application has an array of Document Type.
Each Document Type has an array of Document.
Each Document has a Metadata inside it)
All the three objects types -- Application, Document Type, Document...have a property called name inside them.
I want to sort the entire array of Application objects (and recursively the nested objects as well), based on ascending order of the name property of each object. I had been trying multiple examples, but those are all sorting only the root level objects (Application) and not the nested objects.
Here is one such example I tried:
var simplePropertyRetriever = function(obj:any) {
return obj.name;
};
function sortArrayByName(propertyRetriever, arr:Application[]) {
arr.sort(function (a, b) {
var valueA = propertyRetriever(a);
var valueB = propertyRetriever(b);
if (valueA < valueB) {
return -1;
} else if (valueA > valueB) {
return 1;
} else {
return 0;
}
});
};
Can anybody please advise how to do this?
My sample JSON is this (I have arranged the objects in descending order here, to better explain my use case):
[
{
"name": "Application 2",
"children": [
{
"name": "Operations Manual",
"children": [
{
"name": "2nd-opsManual-app1",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-opsManual-app1",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
},
{
"name": "Interface Contracts",
"children": [
{
"name": "2nd-IntContracts-app1",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-IntContracts-app1",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
}
]
},
{
"name": "Application 2",
"children": [
{
"name": "User Manual",
"children": [
{
"name": "2nd-userManual-app2",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-userManual-app2",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
},
{
"name": "System Design",
"children": [
{
"name": "2nd-SystemDesign-app2",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-SystemDesign-app2",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
}
]
}
]
You could iterate the array and take the children for a new sorting.
function sort(array) {
array.forEach(({ children = [] }) => sort(children));
array.sort((a, b) => a.name.localeCompare(b.name));
}
var data = [{ name: "Application 2", children: [{ name: "Operations Manual", children: [{ name: "2nd-opsManual-app1", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-opsManual-app1", metadata: { size: 56, fileExtension: "pdf" } }] }, { name: "Interface Contracts", children: [{ name: "2nd-IntContracts-app1", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-IntContracts-app1", metadata: { size: 56, fileExtension: "pdf" } }] }] }, { name: "Application 2", children: [{ name: "User Manual", children: [{ name: "2nd-userManual-app2", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-userManual-app2", metadata: { size: 56, fileExtension: "pdf" } }] }, { name: "System Design", children: [{ name: "2nd-SystemDesign-app2", metadata: { size: 56, fileExtension: "docx" } }, { name: "1st-SystemDesign-app2", metadata: { size: 56, fileExtension: "pdf" } }] }] }];
sort(data);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Your code is working, but you're only doing a shallow sort. If you need to also sort each application object's children, you can recursively call sortArrayByName on each application object's children (if they exist).
var simplePropertyRetriever = function(obj) {
return obj.name;
};
function sortArrayByName(propertyRetriever, arr) {
arr.forEach(function(obj) {
if (Array.isArray(obj.children)) {
sortArrayByName(propertyRetriever, obj.children);
}
});
arr.sort(function (a, b) {
var valueA = propertyRetriever(a);
var valueB = propertyRetriever(b);
if (valueA < valueB) {
return -1;
} else if (valueA > valueB) {
return 1;
} else {
return 0;
}
});
};
const data = [
{
"name": "Application 2",
"children": [
{
"name": "Operations Manual",
"children": [
{
"name": "2nd-opsManual-app1",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-opsManual-app1",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
},
{
"name": "Interface Contracts",
"children": [
{
"name": "2nd-IntContracts-app1",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-IntContracts-app1",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
}
]
},
{
"name": "Application 2",
"children": [
{
"name": "User Manual",
"children": [
{
"name": "2nd-userManual-app2",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-userManual-app2",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
},
{
"name": "System Design",
"children": [
{
"name": "2nd-SystemDesign-app2",
"metadata": {
"size": 56,
"fileExtension": "docx"
}
},
{
"name": "1st-SystemDesign-app2",
"metadata": {
"size": 56,
"fileExtension": "pdf"
}
}
]
}
]
}
];
sortArrayByName(simplePropertyRetriever, data);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How To delete items Array in objects state in react

i'm want the each items Array in objects state delete
class App extends Component {
constructor(props) {
super(props);
this.state = {
storeData: [{
"code": "f1",
"name": "storage-no-1",
"capacity": 125,
"temperture": -18,
"humidity": 3,
"saveProducts": [{
"code": "P1",
"id": "1",
"name": "product-no-1",
"size": 20,
},
{
"code": "P1",
"id": "2",
"name": "product-no-2",
"size": 20,
},
]
},
{
"code": "f2",
"name": "storage-no-2",
"capacity": 15,
"temperture": -18,
"humidity": 25,
"saveProducts": [{
"code": "P1",
"id": "1",
"name": "product-no-1",
"size": 20,
},
{
"code": "P1",
"id": "2",
"name": "product-no-2",
"size": 20,
},
]
},
]
}
}
}
my function code :
deleteItem = (saveProductsId,storeCode) => {
console.log("obj",saveProductsId)
console.log("ttt",storeCode);
this.setState(prevState => {
prevState.storeData.map(store => {
if (store.code == storeCode) {
return {
...store,
saveProducts: [
...store.saveProducts.filter(product => product !== saveProductsId)
]
};
} else {
return store;
}
})
})
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Go through each item in storeData and filter the saveProducts where the id !== saveProductsId:
this.setState(prevState => {
const storeData = prevState.storeData.map(s =>
({ ...s, saveProducts: s.saveProducts.filter(p => p.id !== saveProductsId) }));
return { storeData };
})

Dynamically create array of objects from the object with the array values

Currently I have the below object structure,
`let selectedOptions = {
"color": {
"id": "2",
"values": [
{
"value": "red",
"label": "Red",
"id": 1
},
{
"value": "blue",
"label": "Blue",
"id": 2
}
]
},
"size": {
"id": "19",
"values": [
{
"value": "medium",
"label": "Medium",
"id": 2
}
]
},
"demo": {
"id": "19",
"values": [
{
"value": "neylon",
"label": "Neylon",
"id": 2
}
]
}
.
.
.
N
}; `
And want to create array of objects from the above object like as below,
[
{ color: "red", size: "medium", demo: "neylon" },
{ color: "blue", size: "medium", demo: "neylon" }
]
I have tried like below but it didn't worked
https://jsfiddle.net/6Lvb12e5/18/
let cArr = [];
for(key in selectedOptions) {
selectedOptions[key].values.forEach(function(val,i) {
cArr.push({ [key]: val.value })
})
}
Thanks
You could take the wanted parts, like color, size and demo and build a cartesian product out of the given data.
const
cartesian = (a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []),
options = { color: { id: "2", values: [{ value: "red", label: "Red", id: 1 }, { value: "blue", label: "Blue", id: 2 }] }, size: { id: "19", values: [{ value: "small", label: "Small", id: 1 }, { value: "medium", label: "Medium", id: 2 }] }, demo: { id: "19", values: [{ value: "neylon", label: "Neylon", id: 2 }] } },
parts = Object
.entries(options)
.map(([k, { values }]) => [k, values.map(({ value }) => value)]),
keys = parts.map(([key]) => key),
result = parts
.map(([, values]) => values)
.reduce(cartesian)
.map(a => Object.assign(...a.map((v, i) => ({ [keys[i]]: v }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am not sure that is this the best way to do this, and even the data is missing but as a comment, it is quite big to post but can try:
let selectedOptions = {
"color": {
"id": "2",
"values": [
{
"value": "red",
"label": "Red",
"id": 1
},
{
"value": "blue",
"label": "Blue",
"id": 2
}
]
},
"size": {
"id": "19",
"values": [
{
"value": "medium",
"label": "Medium",
"id": 2
}
]
},
"demo": {
"id": "19",
"values": [
{
"value": "neylon",
"label": "Neylon",
"id": 2
}
]
}
};
let cArr = [];
var obj = {};
var glob;
for(key in selectedOptions) {
selectedOptions[key].values.forEach(function(val,i) {
obj[key] = val.value;
}
)
glob = obj;
}
cArr.push(glob);
console.log(cArr)

Categories

Resources