underscore not retaining keys on nested object - javascript

I have an object that looks like this:
var ingredientsObject = {
"Ingredients": [
{ "Section": "Ingredienser", "Name": "salt", "Value": 1, "Unit": "tsk" },
{ "Section": "Ingredienser", "Name": "olivolja", "Value": 1, "Unit": "msk" },
{ "Section": "Ingredienser", "Name": "lasagneplattor, (125 g) färska", "Value": 6, "Unit": "st" },
{ "Section": "Tomatsås", "Name": "salt", "Value": 0.5, "Unit": "tsk" },
{ "Section": "Tomatsås", "Name": "strösocker", "Value": 2, "Unit": "krm" }
{ "Section": "Béchamelsås", "Name": "salt", "Value": 0.5, "Unit": "tsk" },
{ "Section": "Béchamelsås", "Name": "smör", "Value": 2.5, "Unit": "msk" }
]
};
and I am trying to recalculate the value of each ingredient based on the number of servings specified using underscore.
I have tried using mapObject (http://underscorejs.org/#mapObject):
newIngredients = _.mapObject(ingredients.Ingredients, function (val, key) {
return val.Value / modifier;
});
but that returns an object that looks like this:
Object {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 2, 3: 0.3333333333333333, 4: 50, 5: 66.66666666666667, 6: 0.16666666666666666, 7: 0.6666666666666666, 8: 0.25, 9: 0.3333333333333333, 10: 0.3333333333333333, 11: 0.16666666666666666, 12: 0.8333333333333334, 13: 0.16666666666666666, 14: 0.8333333333333334, 15: 1.6666666666666667, 16: 0.6666666666666666}
whereas what I actually want is the original object with only the values changed, as in:
var ingredientsObject = {
"Ingredients": [
{ "Section": "Ingredienser", "Name": "salt", "Value": 0.3333333333333333, "Unit": "tsk" },
{ "Section": "Ingredienser", "Name": "olivolja", "Value": 0.3333333333333333, "Unit": "msk" },
{ "Section": "Ingredienser", "Name": "lasagneplattor, (125 g) färska", "Value": 2, "Unit": "st" }
// and so on...
]
};
How do I achieve this?

Actually ingredients.Ingredients is an array, _.mapObejct expect a object as the first param. You can do this in underscore way:
_.mapObject(ingredientsObject, function(val, key) {
return _.map(val, function(ingredient) {
return _.extend(
{},
ingredient,
{
Value: ingredient.Value / modifier
}
)
})
})

Ok, based on the comments and suggestions I received, I came up with this solution:
newIngredients = _.each(ingredientsObject, function (list) {
_.each(list, function (item) {
item.Value = item.Value / modifier;
});
});
This modifies the value itself without modifying the object structure.
Thanks #nnnnnn for pointing me in the right direction.

Try:
newIngredients = _.map(ingredientsObject.Ingredients, function(item) {
return {
Section: item.Section,
Name: item.Name,
Value: item.Value / modifier,
Unit: item.Unit
};
});

Related

Assigning a grouped index within a javascript array

How would I assign an index to each object within a group in an array using javascript. So starting at zero and counting up inside each group, ordered by the group then the id.
Starting with this
let data = [
{ "id": "AB", "name": "Fred", "group": 1},
{ "id": "BC", "name": "Jane", "group": 2 },
{ "id": "CD", "name": "Mary", "group": 1 },
{ "id": "DE", "name": "Bob", "group": 2 },
{ "id": "EF", "name": "Chris", "group": 1 },
{ "id": "FG", "name": "Steve", "group": 2 },
{ "id": "GH", "name": "Jim", "group": 2 }
]
But adding the groupIndex field for each object.
dataGrouped = [
{ "id": "DE", "name": "Bob", "group": 2, "groupIndex": 1 },
{ "id": "EF", "name": "Chris", "group": 1, "groupIndex": 2 },
{ "id": "BC", "name": "Jane", "group": 2, "groupIndex": 0 },
{ "id": "FG", "name": "Steve", "group": 2, "groupIndex": 2 },
{ "id": "AB", "name": "Fred", "group": 1, "groupIndex": 0},
{ "id": "CD", "name": "Mary", "group": 1, "groupIndex": 1 },
{ "id": "GH", "name": "Jim", "group": 2, "groupIndex": 3 }
]
You could take an object for the indices.
const
indices = {},
data = [{ id: "AB", name: "Fred", group: 1 }, { id: "BC", name: "Jane", group: 2 }, { id: "CD", name: "Mary", group: 1 }, { id: "DE", name: "Bob", group: 2 }, { id: "EF", name: "Chris", group: 1 }, { id: "FG", name: "Steve", group: 2 }, { id: "GH", name: "Jim", group: 2 }],
result = data.map(o => {
indices[o.group] ??= 0;
return { ...o, groupIndex: indices[o.group]++ };
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Presented below is one possible way to achieve the desired objective (viz, assigning group index to array elements). This solution does not address: "ordered by the group then the id."
Code Snippet
// method to assign group-index
// the resulting array may get ordered based on group & group-index (ascending)
const assignGroupIndex = arr => (
Object.values(
arr?.reduce(
(acc, { group, ...rest }) => {
if (!(group in acc)) acc[group] = [];
acc[group].push({
group, ...rest, groupIndex: acc[group].length,
});
return acc;
},
{}
)
).flat()
);
/*
// method to assign group-index for each elt in array
const assignGroupIndex = arr => ( // arg "arr" is the input array
// extract the values from the intermediate result object generated below
Object.values(
// use ".reduce()" to iterate the array and generate an intermediate result
arr?.reduce(
// "acc" is the accumulator, destructure to access "group" & other props
(acc, { group, ...rest }) => {
// if "group" not already in accumulator, set the value as empty array
if (!(group in acc)) acc[group] = [];
// push to the array a new object with "groupIndex" as current length
acc[group].push({
group, ...rest, groupIndex: acc[group].length,
});
// always return the accumulator for each iteration of ".reduce()"
return acc;
},
{} // "acc" - the accumulator is initialized as empty object
)
).flat() // use ".flat()" to remove nested arrays from Object.values()
);
*/
let data = [
{ "id": "AB", "name": "Fred", "group": 1},
{ "id": "BC", "name": "Jane", "group": 2 },
{ "id": "CD", "name": "Mary", "group": 1 },
{ "id": "DE", "name": "Bob", "group": 2 },
{ "id": "EF", "name": "Chris", "group": 1 },
{ "id": "FG", "name": "Steve", "group": 2 },
{ "id": "GH", "name": "Jim", "group": 2 }
];
console.log(
'assigned group-index to array:\n',
assignGroupIndex(data)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.
let data = [
{ "id": "AB", "name": "Fred", "group": 1},
{ "id": "BC", "name": "Jane", "group": 2 },
{ "id": "CD", "name": "Mary", "group": 1 },
{ "id": "DE", "name": "Bob", "group": 2 },
{ "id": "EF", "name": "Chris", "group": 1 },
{ "id": "FG", "name": "Steve", "group": 2 },
{ "id": "GH", "name": "Jim", "group": 2 }
];
let groupCounts = {};
let dataGrouped = data.map(i=>({
...i,
groupIndex: groupCounts[i.group] = ++groupCounts[i.group] || 0
})).sort((a,b)=>a.group-b.group || a.id.localeCompare(b.id));
console.log(dataGrouped);

Comparing 2 objects and making alterations based on Match

I have 2 objects with key-value pairs that should always be identical (match) otherwise I want to modify the value of the key in object #1 to "Some Value - Not available"
Here are my 2 objects:
Object #1
[
{
"name": "John",
"age": "12",
"id": 1
},
{
"name": "tina",
"age": "19",
"id": 2
}]
Object #2 ( name checker)
[
{
"value": "tina"
},
{
"value": "Trevor"
},
{
"value": "Donald"
},
{
"value": "Elon"
},
{
"value": "Pamela"
},
{
"value": "Chris"
},
{
"value": "Jackson"
}
]
I would like to find out if name in Object #1 is found in Object #2 and if it is not found, add " - not available"
e.i
[
{
"name": "John - not available",
"age": "12",
"id": 1
},
{
"name": "tina",
"age": "19",
"id": 2
}
]
Important Note: I'm using ES5 --- not ES6
This should work in ES5
object1.forEach(function(person) {
var found = false;
Object.keys(object2).forEach(function(key) {
if (person.name === object2[key].value) {
found = true;
}
});
if (!found) {
person.name = person.name + " - not available";
}
});

Flatten an object using lodash

I have below this nested object
I need to create an array using this object containing keys. And if keys are object then it should use .dot syntax. and if it is an array then it should give me key.0.keyName. Is it possible to do so?
Output
[
"AllowIPNPayment",
"AllowOnlinePayment",
"MetaData.CreateTime",
"MetaData.LastUpdatedTime",
"CustomField.0.DefinitionId",
"CustomField.0.Name",
"CustomField.0.Type",
...
]
What I have tried is just ugly and does give me expected result. If it is possible with more concise way.
const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 }
let object = {}
for (let k in invoiceObject) {
if (typeof invoiceObject[k] === "object") {
object[k] = {};
for (let l in invoiceObject[k]) {
object[k][l] = "";
}
} else if (typeof invoiceObject[k] === "array") {
object[k] = [];
for (let l in invoiceObject[k][0]) {
object[k][l] = "";
}
} else {
object[k] = "";
}
}
console.log(object)
You can create a recursive function (getSchema) that checks if a value (val) is an object (arrays included), iterate it with _.flatMap(), and collects the keys until it hits a value which is not an object. It then joins the collected keys and returns the string.
const getSchema = (val, keys = []) =>
_.isObject(val) ? // if it's an object or array
_.flatMap(val, (v, k) => getSchema(v, [...keys, k])) // iterate it and call fn with the value and the collected keys
:
keys.join('.') // return the joined keys
const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 }
const result = getSchema(invoiceObject)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Without lodash, the main change is to use Object.entries() to get an array of [key, value] pairs, since Array.flatMap() can't iterate objects:
const getSchema = (val, keys = []) =>
typeof val === 'object' && val !== null ? // if it's an object or array
Object.entries(val) // get [key, value] pairs of object/array
.flatMap(([k, v]) => getSchema(v, [...keys, k])) // iterate it and call fn with the value and the collected keys
:
keys.join('.') // return the joined keys
const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 }
const result = getSchema(invoiceObject)
console.log(result)
inspired by the answer given in this post and understanding you just want to get the property-names, not values, you could do it like this. sorry, this uses plain javascript.
function flattenObjectToKeyArray(ob) {
var toReturn = [];
for (var prop in ob) {
if (!ob.hasOwnProperty(prop)) continue;
if ((typeof ob[prop]) == 'object' && ob[prop] !== null) {
var flatObject = flattenObjectToKeyArray(ob[prop]);
for (var idx = 0; idx < flatObject.length; idx++) {
toReturn.push(prop + '.' + flatObject[idx]);
}
} else {
toReturn.push(prop);
}
}
return toReturn;
}
You could solve this with a recursive function. The function below keeps track of the current keys, and joins them as soon as an end point is reached (a non-object or empty object/array).
const invoiceObject = { "AllowIPNPayment": false, "AllowOnlinePayment": false, "AllowOnlineCreditCardPayment": false, "AllowOnlineACHPayment": false, "domain": "QBO", "sparse": false, "Id": "16", "SyncToken": "1", "MetaData": { "CreateTime": "2020-03-25T15:10:40-07:00", "LastUpdatedTime": "2020-03-26T11:06:49-07:00" }, "CustomField": [{ "DefinitionId": "1", "Name": "Crew #", "Type": "StringType" }], "DocNumber": "1007", "TxnDate": "2020-03-03", "CurrencyRef": { "value": "USD", "name": "United States Dollar" }, "LinkedTxn": [{ "TxnId": "32", "TxnType": "Payment" }], "Line": [{ "Id": "1", "LineNum": 1, "Description": "Custom Design", "Amount": 750, "DetailType": "SalesItemLineDetail", "SalesItemLineDetail": { "ItemRef": { "value": "4", "name": "Design" }, "UnitPrice": 75, "Qty": 10, "TaxCodeRef": { "value": "NON" } } }, { "Amount": 750, "DetailType": "SubTotalLineDetail", "SubTotalLineDetail": {} } ], "TxnTaxDetail": { "TotalTax": 0 }, "CustomerRef": { "value": "13", "name": "uiool" }, "CustomerMemo": { "value": "Thank you for your business and have a great day!" }, "SalesTermRef": { "value": "3" }, "DueDate": "2020-04-02", "TotalAmt": 750, "ApplyTaxAfterDiscount": false, "PrintStatus": "NeedToPrint", "EmailStatus": "NotSet", "BillEmail": { "Address": "uiikoool" }, "Balance": 450 };
function getDotKeys(item, keys = []) {
const isObject = item && typeof item == "object";
if (!isObject) return Array.of(keys.join("."));
const pairs = Array.isArray(item)
? item.map((value, index) => [index, value])
: Object.entries(item);
const isEmpty = !pairs.length;
if (isEmpty) return Array.of(keys.join("."));
const result = [];
for (const [key, value] of pairs) {
const dotKeys = getDotKeys(value, [...keys, key]);
result.push(...dotKeys);
}
return result;
}
console.log(getDotKeys(invoiceObject));
This does produce a different result than what you have in your question, since your solution stops at the second level for objects and third level for arrays. This solution also includes more then only index 0.

Convert sequence of Array in own sequence

Convert Array of List into my Own Order
Current Output:
[
{ "key": "DG Power Output", "value": "6.00", "unit": "kWh", },
{ "key": "DG Run Time", "value": "5999999952", "unit": "minutes", },
{ "key": "Fuel Level (Before)", "value": "8.00", "unit": "liters", }
]
Convert this into
[
{ "key": "Fuel Level (Before)", "value": "8.00", "unit": "liters", },
{ "key": "DG Run Time", "value": "5999999952", "unit": "minutes", },
{ "key": "DG Power Output", "value": "6.00", "unit": "kWh", }
]
You could take an object for getting th right order and sort by the property which describes the order.
var data = [{ key: "DG Power Output", value: "6.00", unit: "kWh" }, { key: "DG Run Time", value: "5999999952", unit: "minutes" }, { key: "Fuel Level (Before)", value: "8.00", unit: "liters" }],
order = { "Fuel Level (Before)": 1, "DG Run Time": 2, "DG Power Output": 3 };
data.sort(({ key: a }, { key: b }) => order[a] - order[b]);
console.log(data);
The most basic I would go would be by accessing the index, let's say
var a = [
{ "key": "DG Power Output", "value": "6.00", "unit": "kWh", },
{ "key": "DG Run Time", "value": "5999999952", "unit": "minutes", },
{ "key": "Fuel Level (Before)", "value": "8.00", "unit": "liters", }
]
Then,
var b = [a[2], a[1], a[0]];
This would give the output you want but it's very risky and error-prone.
I'm not entirely sure what criteria you want to use to sort this array, but the general approach is to write a function that compares two elements and returns a number less than 0 for the first element to come first, 0 if they are equal, and a number greater than 0 for the second element to come first. You can then pass this function to Array.prototype.sort like this for descending order:
const sorter = (a, b) => {
if (a.key == b.key) return 0; // leave elements in place
if (a.key > b.key) return -1; // a should come before b for descending order
return 1; // b should come before a for descending order
};
const arr = [
{ "key": "DG Power Output", "value": "6.00", "unit": "kWh", },
{ "key": "DG Run Time", "value": "5999999952", "unit": "minutes", },
{ "key": "Fuel Level (Before)", "value": "8.00", "unit": "liters", }
];
console.log(arr.sort(sorter));

Javascript sort array by "groups" and maintain order

I have a dataset that looks like this:
[
{
"name": "Item1",
"section": "section1",
"total": 3,
}, {
"name": "Item1",
"section": "section2",
"total": 4,
}{
"name": "Item1",
"section": "section3",
"total": 7,
}, {
"name": "Item2",
"section": "section1",
"total": 1,
}, {
"name": "Item2",
"section": "section2",
"total": 2,
}, {
"name": "Item2",
"section": "section3",
"total": 3,
}
]
I need to sort the array by only the total value in the section 3 item, but maintain the order (section1, section2, then section 3) per name. So for this example Item2 should move all 3 of it's rows above Item1. I've tried sorting by multiple items, but that doesn't maintain the ordering that I need. Should I just get the smallest/biggest, grab the related items and put them into a new array and repeat or is there a more logical way to accomplish this?
I'm also using angular and primeng grid if there's something I can leverage in there.
I would create a map using the name as the key and the total as the value for items where section equals section3. You can then sort using the map.
This will sort all items by the value of the total in section3, and preserve the original sort order where the sort value matches.
const map = new Map<string, number>(this.data
.filter(x => x.section === 'section3')
.map(x => [ x.name, x.total ]));
this.sorted = this.data.slice()
.sort((a, b) => map.get(a.name) - map.get(b.name));
This does rely on the data being structured and ordered as your have specified in your question.
DEMO: https://stackblitz.com/edit/angular-fsswdq
You could
collect all object of the same group and get the total for sorting,
sort by the groups total value,
get a flat array of all objects.
const
data = [{ name: "Item1", section: "section1", total: 3 }, { name: "Item1", section: "section2", total: 4 }, { name: "Item1", section: "section3", total: 7 }, { name: "Item2", section: "section1", total: 1 }, { name: "Item2", section: "section2", total: 2 }, { name: "Item2", section: "section3", total: 3 }],
result = Object
.values(data.reduce((r, o) => {
r[o.name] = r[o.name] || { payload: [] };
r[o.name].payload.push(o);
if (o.section === 'section3') r[o.name].total = o.total;
return r;
}, {}))
.sort(({ total: a }, { total: b }) => a - b)
.flatMap(({ payload }) => payload);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Priority sort
const data = [{"name":"Item1","section":"section1","total":3},{"name":"Item1","section":"section2","total":4},{"name":"Item1","section":"section3","total":7},{"name":"Item2","section":"section1","total":1},{"name":"Item2","section":"section2","total":2},{"name":"Item2","section":"section3","total":3}];
console.log(
data.sort((a, b) => {
const diff = a.total - b.total;
if (diff) return diff;
return b.section.localeCompare(a.section);
})
);
.as-console-row {color: blue!important}
var array = [
{
"name": "Item1",
"section": "section1",
"total": 3,
}, {
"name": "Item1",
"section": "section2",
"total": 4,
},{
"name": "Item1",
"section": "section3",
"total": 7,
}, {
"name": "Item2",
"section": "section1",
"total": 1,
}, {
"name": "Item2",
"section": "section2",
"total": 2,
}, {
"name": "Item2",
"section": "section3",
"total": 3,
}
];
array = array.sort((o1, o2)=>{
if(o1.section === o2.section && o1.section === 'section3') {
return o1.total - o2.total;
} else {
return o1.section === 'section3' ? 1 : -1;
}
});
console.log(array);
Here's the output
[
{
"name": "Item1",
"section": "section1",
"total": 3
},
{
"name": "Item1",
"section": "section2",
"total": 4
},
{
"name": "Item2",
"section": "section1",
"total": 1
},
{
"name": "Item2",
"section": "section2",
"total": 2
},
{
"name": "Item2",
"section": "section3",
"total": 3
},
{
"name": "Item1",
"section": "section3",
"total": 7
}
]
You first need to "Group" the data set by name and then do the sorting by total.
let items = [{
"name": "Item1",
"section": "section1",
"total": 3,
}, {
"name": "Item1",
"section": "section2",
"total": 4,
}, {
"name": "Item1",
"section": "section3",
"total": 7,
}, {
"name": "Item2",
"section": "section1",
"total": 1,
}, {
"name": "Item2",
"section": "section2",
"total": 2,
}, {
"name": "Item2",
"section": "section3",
"total": 3,
}];
let groups = {};
for (let item of items) {
if (!groups[item.name]) {
groups[item.name] = {
data: []
};
}
// Grouping by `name`
groups[item.name].data.push(item);
// Store the `total`
if (item.section == "section3") {
groups[item.name].key = item.total;
}
}
// sort the groups, this will maintain the order of sections (1,2 and 3) in each group
let sortedGroups = Object.values(groups).sort((a, b) => {
return a.key - b.key; // ascending
});
// then flatten the groups
let flatten = [].concat(...sortedGroups.map(x => x.data));
console.log(flatten);

Categories

Resources