I tried with no success to sort an array of multiple objects of objects.
Here my database:
var jsonDatas = [ { "type": "Voiture", "items": [ { "name": "Fiat Punto", "description": "Je suis une voiture", "price": 10000, "quantity": 2, }, { "name": "Porsche 911", "description": "Je suis une belle voiture", "price": 80000, "quantity": 0, }, ], }, { "type": "Maison", "items": [ { "name": "Villa sur la plage", "description": "Quelle belle vue", "price": 870000, "quantity": 1, }, { "name": "Maison à la campagne", "description": "Vive le calme", "price": 170000, "quantity": 3, } ], }
I tried this for example:
function sortDatasASC(){ database.forEach(element => element.items.sort((a, b) => (a.name > b.name)? 1: -1)), catalogFiltered();
I tried to create an intermediate array to push items and then reassociate with the type but it doesn't work.
For example, this work for a checkbox who display products if there are on stock, but can't duplicate it for a sorting
const choiceStock = document.getElementById('stockCheck').addEventListener('change', function () { let datas = []; if (this.checked) { let filter = []; database.forEach(element => filter.push({ 'type': element.type, 'items': element.items.filter(test => test.quantity > 0) }) ); datas = filter; } else { datas = database; } showCatalog(datas); });
If you have any ideas??
Thanks in advance.
Your data is grouped by types but since you want it sorted by name instead of by type/name, I would flatten the structure into an array of objects and then apply the logic as you have above:
const flattened = jsonDatas.reduce((acc, entry) => {
//since we dont want to lose the type information I'm cloning
//each item and adding a type property to it.
const items = entry.items.map(i => ({ ...i, type: entry.type }));
return acc.concat(items);
}, []);
flattened.sort((a, b) => {
if (a.name.toLowerCase() === b.name.toLowerCase()) {
return 0;
}
return a.name.toLowerCase() > b.name.toLowerCase() ? -1 : 1;
});
//the type is retained so we can rebuild the structure:
const restructured = flattened.map(item => ({
type: item.type,
items: [item],
}));
console.log(flattened);
console.log(restructured);
I'm also making the assumption that you want a case insensitive sort. If that's not the case, go ahead and remove the "toLowerCase" calls.
First you need to make a flat array. To be able to sort by type
property, you need to add the type
to each element. You can also change the sorting function depending on the property type (strng / number). This is just a simple example: :
const jsonDatas=[{type:"Voiture",items:[{name:"Fiat Punto",description:"Je suis une voiture",price:1e4,quantity:2},{name:"Porsche 911",description:"Je suis une belle voiture",price:8e4,quantity:0}]},{type:"Maison",items:[{name:"Villa sur la plage",description:"Quelle belle vue",price:87e4,quantity:1},{name:"Maison à la campagne",description:"Vive le calme",price:17e4,quantity:3}]}]; const flatData = jsonDatas.flatMap(({ items, type }) => items.map(item => ({...item, type }))); const sortBy = (arr, property, direction = 'asc') => { if (arr.length === 0) return []; const propertyType = typeof arr.at(0)[property]; const sortCallbacks = { string: (e1, e2) => e1[property].localeCompare(e2[property]), number: (e1, e2) => e1[property] - e2[property], }; const sortedAsc = arr.sort(sortCallbacks[propertyType]); if (direction === 'asc' ) return sortedAsc; return sortedAsc.reverse(); }; console.log(sortBy(flatData, 'name' )); console.log(sortBy(flatData, 'type', 'dsc')); console.log(sortBy(flatData, 'price', 'dsc'));
.as-console-wrapper { max-height: 100%;important: top; 0; }
I finally find the solution, see below if this can helps some of you:
function createArrayToSort(database) { let datas = []; database.forEach(element => element.items.forEach(items => datas.push({'type': element.type, 'items': [items]}) )) return datas; }; function sortByName(direction){ let datas = createArrayToSort(database); if(direction == "ASC") { datas.sort((a, b) => (a.items[0].name > b.items[0].name)? 1: -1); } else { datas.sort((a, b) => (b.items[0].name > a.items[0].name)? 1: -1); } showCatalog(datas); }; function sortByPrice(direction){ let datas = createArrayToSort(database); if(direction == "ASC") { datas.sort((a, b) => (a.items[0].price > b.items[0].price)? 1: -1); } else { datas.sort((a, b) => (b.items[0].price > a.items[0].price)? 1: -1); } showCatalog(datas); }; const nameASC = document.getElementById('nameASC').addEventListener('click', function () { sortByName('ASC') });
The jsonDatas
definition your shown in the snippet of your question does not match the screenshot, where other values are shown (eg Peugeot 205 as a "type": "Voiture"
entry). The presence of that Peugeot 205 value denotes that the complete jsonDatas
array contains other objects of the same type ( Voiture
or Maison
) apart from the objects you listed.
If that is the way the jsonDatas
is structured then, to have it sorted as you want, you would need to do two things:
First: convert jsonDatas
into an array of objects such as those objects contains an items
array with just one element. That will let you manage the order of the records individually. In my snippet below that would be the result in the singleItem
array.
Second: after you have transformed your input into singleItem
style array, then you can simply sort that array by the name of the unique item in the items
array (that is: .items[0].name
).
Below you can see the working code. I used flatMap and map as these are convenient methods to do the transformation of step #1.
var jsonDatas = [ { "type": "Voiture", "items": [ { "name": "Fiat Punto", "description": "Je suis une voiture", "price": 10000, "quantity": 2, }, { "name": "Porsche 911", "description": "Je suis une belle voiture", "price": 80000, "quantity": 0, }, ], }, { "type": "Maison", "items": [ { "name": "Villa sur la plage", "description": "Quelle belle vue", "price": 870000, "quantity": 1, }, { "name": "Maison à la campagne", "description": "Vive le calme", "price": 170000, "quantity": 3, } ], } ] var singleItem = jsonDatas.flatMap(t => t.items.map(i => { return { type: t.type, items: [ i ] } })) var sorted = singleItem.sort((a, b) => a.items[0].name.localeCompare(b.items[0].name)) console.log(sorted)
For simple sorting via type is just like be
jsonDatas.sort((a, b) => (a.type > b.type)? 1: -1)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.