javascript | Object grouping
Try with something like this:
function groupBy(collection, property) {
var i = 0, val, index,
values = [], result = [];
for (; i < collection.length; i++) {
val = collection[i][property];
index = values.indexOf(val);
if (index > -1)
result[index].push(collection[i]);
else {
values.push(val);
result.push([collection[i]]);
}
}
return result;
}
var obj = groupBy(list, "group");
Keep in mind that Array.prototype.indexOf
isn't defined in IE8 and older, but there are common polyfills for that.
How can I group an array of objects by key?
Timo's answer is how I would do it. Simple _.groupBy
, and allow some duplications in the objects in the grouped structure.
However the OP also asked for the duplicate make
keys to be removed. If you wanted to go all the way:
var grouped = _.mapValues(_.groupBy(cars, 'make'),
clist => clist.map(car => _.omit(car, 'make')));
console.log(grouped);
Yields:
{ audi:
[ { model: 'r8', year: '2012' },
{ model: 'rs5', year: '2013' } ],
ford:
[ { model: 'mustang', year: '2012' },
{ model: 'fusion', year: '2015' } ],
kia:
[ { model: 'optima', year: '2012' } ]
}
If you wanted to do this using Underscore.js, note that its version of _.mapValues
is called _.mapObject
.
Most efficient method to groupby on an array of objects
If you want to avoid external libraries, you can concisely implement a vanilla version of groupBy()
like so:
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
console.log(groupBy(['one', 'two', 'three'], 'length'));
// => {"3": ["one", "two"], "5": ["three"]}
Grouping nested object properties
Here's my take. A series of nested for for...in
loops. Tried to optimize for readability.
const object = {
1: { one: { a: 5, b: 6, c: 7, d: 8 } },
2: { one: { a: 6, b: 9, c: 10, d: 12, e: 1 } },
3: { one: { a: 3, b: 4, c: 9 } },
};
const result = {};
for (const group in object) {
for (const num in object[group]) {
if (!result[num]) {
result[num] = {};
}
for (const letter in object[group][num]) {
if (!result[num][letter]) {
result[num][letter] = [];
}
result[num][letter].push(object[group][num][letter])
}
}
}
console.log(result)
How to group array of objects by certain property values
A back to the future answer :
Not yet supported by lot of browsers but will come soon (Stage 3 for TC39) and already available in polyfill core-js) is the new groupBy
method on the array object.
This will allows you to do it directly like this :
employees.groupBy(employee => employee.company);
or even :
employees.groupBy(({company}) => company);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/groupBy
Javascript - grouping an array and then sorting the grouped result based on length
From my above comment ...
"In case the OP depends on key insertion order (though it would even work) of an object (because this is what the OP is asking for) then the OP's entire data handle approach is at question. What one could do instead ... create a sorted array of object-items from the former object of grouped entries."
The next provided solution does exactly what already got proposed.
In order to achieve the intermediate grouping goal one would reduce
the given data-structure into an object of grouped entries (each entry holding an array of some of the former data-array items.
Each of the entries
now can be map
ped into an own object of the still unsorted result array which within a last step will be sort
ed by either each object's sole array-value length
-property or by a locale comparison of the single property names (keys).
function groupAndCollectBySameKeyValue({ key, result }, item) {
const groupValue = item[key];
(result[groupValue] ??= []).push(item);
return { key, result };
}
var dataArr = [
{ permalink: 'link', subreddit: 'laravel' },
{ permalink: 'link', subreddit: 'mac' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'laravel' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'chrome' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'laravel' },
];
console.log(
dataArr
.reduce(groupAndCollectBySameKeyValue, {
key: 'subreddit',
result: {},
})
.result
);
console.log(
Object
.entries(
dataArr
.reduce(groupAndCollectBySameKeyValue, {
key: 'subreddit',
result: {},
})
.result
)
// create object from grouped entry (key-value pair).
.map(([key, value]) => ({ [key]: value }))
.sort((a, b) =>
// ... either by array length ...
Object.values(b)[0].length - Object.values(a)[0].length
// ... or by locale alphanumeric precedence.
|| Object.keys(a)[0].localeCompare(Object.keys(b)[0])
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Grouping an array of objects and assign new combined value to each object
I'd say the most efficient way to do it would be to create an object which maps school to an array of names. Then map
the initial array:
var initialArr= [
{name:"A", school:"LFM"},
{name:"B", school:"LFM"},
{name:"C", school:"PBE"},
{name:"D", school:"LFM"},
{name:"E", school:"BPE"},
{name:"F", school:"LFM"}
];
var schoolObj = initialArr.reduce((a, { name, school }) => {
a[school] = (a[school] || []);
a[school].push(name);
return a;
}, {});
var expectedResult = initialArr.map(e => {
e.alumni = schoolObj[e.school].join("-");
return e;
});
console.log(expectedResult);
Grouping Array element using two properties
Here is what you are looking for, without using of any additional libraries:
const data = [{"id":"myid","base":{"orderNumber":"0500332","marketPlaceOrderCode":"","creationDate":"2022-06-14T10:49:10Z","source":"sfcc","brands":["KI", "SA"],"country":"BG","status":"new","totalEuro":12,"currency":"BGN","units":1,"coupons":null,"shipping":{"id":"BG01","name":"Speedy COD","status":"not_shipped"}},"psp":{"name":"payu","method":null,"status":null},"tms":null},{"id":"DEC-00500331","base":{"orderNumber":"id2","marketPlaceOrderCode":"","creationDate":"2022-06-14T10:41:29Z","source":"sfcc","brands":["DEC"],"country":"UK","status":"new","totalEuro":57,"currency":"GBP","units":1,"coupons":null,"shipping":{"id":"ECA_DPD_ST","name":"Standard shipping","status":"not_shipped"}},"psp":{"name":"adyen","method":null,"status":"paid"},"tms":null}];
const rawResult = normalizeData(data);
console.log(makeItReadable(rawResult));
function normalizeData(data) {
const result = {};
data.forEach((order) => {
const orderData = order.base;
// add country to result (if not exists)
if (!result[orderData.country]) {
result[orderData.country] = {};
}
orderData.brands.forEach((brand) => {
// add brand to exact country (if not exists)
if (!result[orderData.country][brand]) {
result[orderData.country][brand] = {};
}
// add status to exact brand and country (if not exists)
if (!result[orderData.country][brand][orderData.status]) {
result[orderData.country][brand][orderData.status] = 0;
}
// increment status count
++result[orderData.country][brand][orderData.status];
});
});
return result;
}
function makeItReadable(rawData) {
const readableResult = [];
Object.keys(rawData).map((country) => {
Object.keys(rawData[country]).map((brand) => {
readableResult.push({country, brand, ...rawData[country][brand]});
});
});
return readableResult;
}
This code will give you the following result:
[
{ country: 'BG', brand: 'KI', new: 1 },
{ country: 'BG', brand: 'SA', new: 1 },
{ country: 'UK', brand: 'DEC', new: 1 }
]
Grouping values into one array of objects from two objects based on differing keys
You can loop over the keys of the ingredients object and create the desired array by slicing out the ingredient number and looking for the corresponding measure for that number.
const
ingredients = { strIngredient1: "Light rum", strIngredient2: "Lime", strIngredient3: "Sugar", strIngredient4: "Mint", strIngredient5: "Soda water" },
measurements = { strMeasure1: "2-3 oz", strMeasure2: "Juice of 1", strMeasure3: "2 tsp", strMeasure4: "2-4" },
result = Object.keys(ingredients).map((k) => ({
ingredient: ingredients[k],
measure: measurements[`strMeasure${k.slice(13)}`] ?? "",
}));
console.log(result);
Related Topics
How to Reload or Re-Render the Entire Page Using Angularjs
How to Suppress the Browser's Authentication Dialog
How to Overcome the Cors Issue in Reactjs
React - Preventing Form Submission
JavaScript to Sort Contents of Select Element
About Closure, Lexicalenvironment and Gc
Why the Function Called by Settimeout Has No Callstack Limit
Display a Popup Only Once Per User
Jquery Function to Get All Unique Elements from an Array
Jquery Difference Between Change and Click Event of Checkbox
How to Check Whether an Object Is a Date
What Is This Practice Called in JavaScript
How to Sort Numbers Correctly with Array.Sort()
Method for Streaming Data from Browser to Server via Http
This' Does Not Work Properly in Another Event. I'm Clueless as to Why
JavaScript Can't Access Private Properties