Reduce and sum array of objects (JS) [duplicate] - javascript

This question already has answers here:
Sum JavaScript object propertyA values with the same object propertyB in an array of objects
(12 answers)
Group by, and sum, and generate an object for each array in JavaScript
(4 answers)
How to group by and sum an array of objects? [duplicate]
(2 answers)
Group objects by multiple properties in array then sum up their values
(16 answers)
Closed 3 years ago.
My data:
arr: [],
models: [
{ id: 1, name: "samsung", seller_id: 1, count: 56 },
{ id: 1, name: "samsung", seller_id: 2, count: 68 },
{ id: 2, name: "nokia", seller_id: 2, count: 45 },
{ id: 2, name: "nokia", seller_id: 3, count: 49 }
]
Expected Arr:
arr: [
{ id: 1, name: "samsung", count: 124 },
{ id: 2, name: "nokia", count: 94 }
]
It's my code to simplify models by removing repeated id:
this.models.forEach(mdl => {
if (!this.arr.some(obj => obj.id === mdl.id)) {
this.arr.push(mdl);
}
});
But I can't sum counts.
How can I do that?

You can use Array.reduce():
var models = [
{ id: 1, name: "samsung", seller_id: 1, count: 56 },
{ id: 1, name: "samsung", seller_id: 2, count: 68 },
{ id: 2, name: "nokia", seller_id: 2, count: 45 },
{ id: 2, name: "nokia", seller_id: 3, count: 49 }
];
var arr = models.reduce((acc, item) => {
let existItem = acc.find(({id}) => item.id === id);
if(existItem) {
existItem.count += item.count;
} else {
acc.push(item);
}
return acc;
}, []);
console.log(arr);
So, for your code, you can use this.arr and this.models replacing those variables from above which will look something like:
this.arr = this.models.reduce((acc, item) => {
let existItem = acc.find(({id}) => item.id === id);
if(existItem) {
existItem.count += item.count;
} else {
acc.push(item);
}
return acc;
}, []);

You can use Object.values instead of some. Inside the reduce callback create an object with key as id and value from the models. Then use Object.values to create an array of the values
let models = [{
id: 1,
name: "samsung",
seller_id: 1,
count: 56
},
{
id: 1,
name: "samsung",
seller_id: 2,
count: 68
},
{
id: 2,
name: "nokia",
seller_id: 2,
count: 45
},
{
id: 2,
name: "nokia",
seller_id: 3,
count: 49
}
]
let data = models.reduce((acc, curr) => {
if (!acc[curr.id]) {
acc[curr.id] = curr;
} else {
acc[curr.id].count += curr.count
}
return acc;
}, {})
console.log(Object.values(data))

Related

How can I see if Object Array has elements in Another Object Array?

Is there a way to tell if an object array has any common elements to another object array, and what that object intersect is? (like a Contains function). In the example below,ProductId3 in Object Array 1, is also contained in Object Array 2.
I'm thinking of using a double for loop . However is there a more efficient/optimal way, or shorthand ecma or lodash function?
We are checking all object members, not just ProductId.
array1.forEach(arr1 => {
array2.forEach(arr2 => {
if (arr1.productId === arr2.productId &&
arr1.productName === arr2.productName ...
Object Array 1:
[
{
ProductId: 50,
ProductName: 'Test1',
Location: 77,
Supplier: 11,
Quantity: 33
},
{
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
}
]
Object Array 2:
[
{
ProductId: 1,
ProductName: 'ABC',
Location: 3,
Supplier: 4,
Quantity: 52
},
{
ProductId: 2,
ProductName: 'DEF',
Location: 1,
Supplier: 2,
Quantity: 87
},
{
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
},
{
ProductId: 4,
ProductName: 'XYZ',
Location: 5,
Supplier: 6,
Quantity: 17
}
]
Resources:
How to determine if Javascript array contains an object with an attribute that equals a given value?
Javascript: Using `.includes` to find if an array of objects contains a specific object
Is there a way to tell if an object array has any common elements to another object array ? - Yes you can achieve this with the help of Array.some() method. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false.
const array1 = [{
ProductId: 50,
ProductName: 'Test1',
Location: 77,
Supplier: 11,
Quantity: 33
}, {
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
}];
const array2 = [{
ProductId: 1,
ProductName: 'ABC',
Location: 3,
Supplier: 4,
Quantity: 52
}, {
ProductId: 2,
ProductName: 'DEF',
Location: 1,
Supplier: 2,
Quantity: 87
}, {
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
}, {
ProductId: 4,
ProductName: 'XYZ',
Location: 5,
Supplier: 6,
Quantity: 17
}];
const isCommonProducts = array2.some(({ ProductId }) => array1.map(obj => obj.ProductId).includes(ProductId));
console.log(isCommonProducts);
Update : As per the author comment, we have to check all the properties of an object. Hence, we can achieve that by comparing the JSON string by converting the object into a string.
Live Demo :
const array1 = [{
ProductId: 50,
ProductName: 'Test1',
Location: 77,
Supplier: 11,
Quantity: 33
}, {
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
}];
const array2 = [{
ProductId: 1,
ProductName: 'ABC',
Location: 3,
Supplier: 4,
Quantity: 52
}, {
ProductId: 2,
ProductName: 'DEF',
Location: 1,
Supplier: 2,
Quantity: 87
}, {
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
}, {
ProductId: 4,
ProductName: 'XYZ',
Location: 5,
Supplier: 6,
Quantity: 17
}];
const getFilteredProducts = array2.filter(productObj => JSON.stringify(array1).indexOf(JSON.stringify(productObj)) !== -1);
console.log(getFilteredProducts);
If we can assume that each array's elements (we will call them sub-dictionaries) contain exactly the same keys in the same order, then this is my idea:
Convert each array into a new array whose elements are the JSON representations of the original sub-dictionaries values. This is an o(N) operation performed twice.
Of the new, converted arrays find the shortest one. Convert the other into a set. This is also o(N).
For each element of the shorter converted array, check to see if the set contains this value. This is also o(N).
let arr1 = [
{
ProductId: 50,
ProductName: 'Test1',
Location: 77,
Supplier: 11,
Quantity: 33
},
{
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
}
];
let arr2 = [
{
ProductId: 1,
ProductName: 'ABC',
Location: 3,
Supplier: 4,
Quantity: 52
},
{
ProductId: 2,
ProductName: 'DEF',
Location: 1,
Supplier: 2,
Quantity: 87
},
{
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
},
{
ProductId: 4,
ProductName: 'XYZ',
Location: 5,
Supplier: 6,
Quantity: 17
}
];
// Convert each sub-array's values to JSON string:
let arr1New = arr1.map(function(arr) {return JSON.stringify(Object.values(arr));});
let arr2New = arr2.map(function(arr) {return JSON.stringify(Object.values(arr));});
// Find shortest array of JSON strings:
const l1 = arr1New.length;
const l2 = arr2New.length;
// enumerate shortest list
let list, set, l, arr;
if (l1 <= l2) {
list = arr1New;
set = new Set(arr2New);
l = l1;
arr = arr1;
}
else {
list = arr2New;
set = new Set(arr1New);
l = l2;
arr = arr2;
}
for(let i = 0; i < l; i++) {
if (set.has(list[i])) {
console.log(arr[i]);
}
}
Update
If the sub-dictionary keys are not necessarily in order, then we have to create new sub-dictionaries from these where the keys are in order:
// Create function to create new dictionaries sorted by keys
function sort_dict(d) {
items = Object.keys(d).map(function(key) {
return [key, d[key]];
});
items.sort(function(first, second) {
return first[0] < second[0] ? -1 : (first[0] > second[0] ? 1 : 0);
});
sorted_dict = {};
items.forEach(function(x) {
sorted_dict[x[0]] = x[1];
});
return(sorted_dict);
}
// And then we have these modified lines:
// Convert each sub-array's values to JSON string:
let arr1New = arr1.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});
let arr2New = arr2.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});
Modified Code
let arr1 = [
{
ProductId: 50,
ProductName: 'Test1',
Location: 77,
Supplier: 11,
Quantity: 33
},
{
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25,
ProductId: 3 // Not in the same order as the others
}
];
let arr2 = [
{
ProductId: 1,
ProductName: 'ABC',
Location: 3,
Supplier: 4,
Quantity: 52
},
{
ProductId: 2,
ProductName: 'DEF',
Location: 1,
Supplier: 2,
Quantity: 87
},
{
ProductId: 3,
ProductName: 'GHI',
Location: 1,
Supplier: 4,
Quantity: 25
},
{
ProductId: 4,
ProductName: 'XYZ',
Location: 5,
Supplier: 6,
Quantity: 17
}
];
function sort_dict(d) {
items = Object.keys(d).map(function(key) {
return [key, d[key]];
});
items.sort(function(first, second) {
return first[0] < second[0] ? -1 : (first[0] > second[0] ? 1 : 0);
});
sorted_dict = {};
items.forEach(function(x) {
sorted_dict[x[0]] = x[1];
});
return(sorted_dict);
}
// Convert each sub-array's values to JSON string:
let arr1New = arr1.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});
let arr2New = arr2.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});
// Find shortest array of JSON strings:
const l1 = arr1New.length;
const l2 = arr2New.length;
// enumerate shortest list
let list, set, l, arr;
if (l1 <= l2) {
list = arr1New;
set = new Set(arr2New);
l = l1;
arr = arr1;
}
else {
list = arr2New;
set = new Set(arr1New);
l = l2;
arr = arr2;
}
for(let i = 0; i < l; i++) {
if (set.has(list[i])) {
console.log(arr[i]);
}
}
For a simple yet reasonably fast solution, you can (1) use a Set of productIds from the first array, then (2) filter the second array based on the ids from the first one, this you only have to go over each array once O(n).
let arr1 = [
{
ProductId: 50,
ProductName: "Test1",
Location: 77,
Supplier: 11,
Quantity: 33,
},
{
ProductId: 3,
ProductName: "GHI",
Location: 1,
Supplier: 4,
Quantity: 25,
},
];
let arr2 = [
{
ProductId: 1,
ProductName: "ABC",
Location: 3,
Supplier: 4,
Quantity: 52,
},
{
ProductId: 2,
ProductName: "DEF",
Location: 1,
Supplier: 2,
Quantity: 87,
},
{
ProductId: 3,
ProductName: "GHI",
Location: 1,
Supplier: 4,
Quantity: 25,
},
{
ProductId: 4,
ProductName: "XYZ",
Location: 5,
Supplier: 6,
Quantity: 17,
},
];
const getCommonItems = (arr1, arr2) => {
let firstIdSet = new Set(arr1.map((product) => product.ProductId)); //1
return arr2.filter((product) => firstIdSet.has(product.ProductId)); //2
};
console.log(getCommonItems(arr1, arr2));
If you want a deep equality comparison(for nested objects or for all (key, value) pairs), I would suggest a slightly better approach which is using the base64 encoding/decoding to improve on comparison performance.
So my approach is to:
merge the arrays and convert the object to base64 strings.
Group the recurrences together
Filter on duplicates
revert the base64 strings into their original object.
const convertObjToBase64 = o => btoa(JSON.stringify(o));
const convertBase64ToObj = str => JSON.parse(atob(str));
const arrayToObjCount = arr => arr.reduce((res, v) => {
res[v] = (res[v] ?? 0) + 1;
return res;
}, {});
const findDuplicateObjectsInMultipleArrays = (...arrays) => {
const base64Array = Array.from(arrays.flat(), convertObjToBase64);
const objCount = arrayToObjCount(base64Array);
const duplicates = Object.entries(objCount).reduce((prev, [k, v]) => {
if (v > 1) {
prev.push(convertBase64ToObj(k));
}
return prev;
}, []);
return duplicates;
}
let arr1 = [{
ProductId: 50,
ProductName: 'Test1',
Location: {
LocationId: 77,
LocationName: 'Location 77'
},
Supplier: 11,
Quantity: 33
},
{
ProductId: 3,
ProductName: 'GHI',
Location: {
LocationId: 1,
LocationName: 'Location 1'
},
Supplier: 4,
Quantity: 25
}
];
let arr2 = [{
ProductId: 1,
ProductName: 'ABC',
Location: {
LocationId: 3,
LocationName: 'Location 3'
},
Supplier: 4,
Quantity: 52
},
{
ProductId: 2,
ProductName: 'DEF',
Location: {
LocationId: 1,
LocationName: 'Location 1'
},
Supplier: 2,
Quantity: 87
},
{
ProductId: 3,
ProductName: 'GHI',
Location: {
LocationId: 1,
LocationName: 'Location 1'
},
Supplier: 4,
Quantity: 25
},
{
ProductId: 4,
ProductName: 'XYZ',
Location: {
LocationId: 5,
LocationName: 'Location 5'
},
Supplier: 6,
Quantity: 17
}
];
let arr3 =[
{
ProductId: 2,
ProductName: 'DEF',
Location: {
LocationId: 1,
LocationName: 'Location 1'
},
Supplier: 2,
Quantity: 87
},
{
ProductId: 3,
ProductName: 'GHI',
Location: {
LocationId: 2,
LocationName: 'Location 2'
},
Supplier: 4,
Quantity: 25
},
{
ProductId: 4,
ProductName: 'XYZ',
Location: {
LocationId: 6,
LocationName: 'Location 5'
},
Supplier: 6,
Quantity: 17
}
];
console.log(findDuplicateObjectsInMultipleArrays(arr1, arr2, arr3));
I will post two solutions:
First Solution is readable one
Code is not 100% performance optimized, but it is readable and elegant.
Playground link with working code
First, we need a method that compares two objects of any type. The method compares the first-level properties, so if we have nested object properties, it will compare them by reference.
const areTheSame = (a: any, b: any) => {
const objAProps = Object.keys(a).filter(key => typeof a[key] !== "function")
const objBProps = Object.keys(b).filter(key => typeof b[key] !== "function")
if (objAProps.length !== objBProps.length) {
return false;
}
return objAProps.every((propName) => a[propName] === b[propName]);
}
And then we can implement readable intersect method which will work for any array types:
const getIntersection = (array1: Array<any>, array2: Array<any>) => {
return array1.filter(a1Item => array2.some(a2Item => areTheSame(a1Item, a2Item)));
}
The Second solution is performance-oriented, its drawback is that it is not so readable
First, we calculate the has for all objects, then within a single forEach loop we can identify the intersection based on that Hash. I have used md5, but any hash algorithm or library can be used.
Hers is stack blitz link playground. It can be run, ignore the import error.
const getArrayIntersection = (
firstArray: Array<any>,
secondArray: Array<any>
) => {
const array1Hashed = firstArray.map((i) => md5(JSON.stringify(i)));
const array2Set = new Set(secondArray.map((i) => md5(JSON.stringify(i))));
const result: Array<any> = [];
array1Hashed.forEach((itemHash, index) => {
if (array2Set.has(itemHash)) {
result.push(firstArray[index]);
}
});
return result;
};
Just to piggyback #Rohìt Jíndal, you can check if an array has a specific object like so:
const resultObj = arr1.filter(obj => obj.id=== "whatever" && obj.productname == "whatever") // ETC ETC

How does one order array-items of complex data-structures by a specific but deeply nested property-value?

This is my array, I have an object and then a count of how many repeats Id have for example the first object has the Id 2 repeated 3 times.
[{
Id: 1,
Info: "Info",
Category: [
{ Id: 2, count: 3 },
{ Id: 4, count: 1 },
{ Id: 8, count: 1 },
{ Id: 18, count: 1 },
{ Id: 9, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 2,
Info: "Info 2",
Category: [
{ Id: 2, count: 3 },
{ Id: 9, count: 2 },
{ Id: 21, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 3,
Info: "Info 3",
Category: [
{ Id: 4, count: 1 },
{ Id: 11, count: 1 },
{ Id: 9, count: 1 },
],
}]
Now I need to order this array based on an Id for example the number "9" so if the first object has the Maximus count of the id 9 of all it will be the first and the others whit minus count would be bellow, like this, the number 9 will be a random number.
[{
Id: 2,
Info: "Info 2",
Category: [
{ Id: 2, count: 3 },
{ Id: 9, count: 2 },
{ Id: 21, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 1,
Info: "Info",
Category: [
{ Id: 2, count: 3 },
{ Id: 4, count: 1 },
{ Id: 8, count: 1 },
{ Id: 18, count: 1 },
{ Id: 9, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 3,
Info: "Info 3",
Category: [
{ Id: 4, count: 1 },
{ Id: 11, count: 1 },
{ Id: 9, count: 1 },
],
}]
Using Array.prototype.sort one needs to write a function which compares two array/list items according to the OP's requirements.
Such a comparator is expected to return a number value either grater than Zero or lower than Zero or Zero itself in case of item equality.
Thus one needs to find two different counts, one count for each item which will be found by searching an item's Category array by an additionally provided id value.
In order to keep the compare function reusable it is implemented as a function which allows a context to be bound to it which in the OP's case is an object that features the id one is looking for ... e.g. something like ... { id: 9 } or { id: 4 } ...
function compareByBoundIdCountOfItemCategoryList(a, b) {
const { id } = this;
const aCount = a.Category.find(ctgry => ctgry.Id === id)?.count ?? -1;
const bCount = b.Category.find(ctgry => ctgry.Id === id)?.count ?? -1;
// in case of equal counts compare the `Category` array's lengths'.
return (bCount - aCount) || (b.Category.length - a.Category.length);
}
const sampleList = [{
Id: 1,
Info: "Info",
Category: [
{ Id: 2, count: 3 },
{ Id: 4, count: 1 },
{ Id: 8, count: 1 },
{ Id: 18, count: 1 },
{ Id: 9, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 2,
Info: "Info 2",
Category: [
{ Id: 2, count: 3 },
{ Id: 9, count: 2 },
{ Id: 21, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 3,
Info: "Info 3",
Category: [
{ Id: 4, count: 1 },
{ Id: 11, count: 1 },
{ Id: 9, count: 1 },
],
}];
console.log(
'{ id: 9 } ...',
sampleList
.sort(compareByBoundIdCountOfItemCategoryList.bind({ id: 9 }))
);
console.log(
'{ id: 4 } ...',
sampleList
.sort(compareByBoundIdCountOfItemCategoryList.bind({ id: 4 }))
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
As one of the comments does point out, the above code requires a version of at least node 14.0.0 due to the function compareByBoundIdCountOfItemCategoryList which uses both the Optional Chaining Operator / ?. and the Nullish Coalescing Operator / ??.
In order to let the script not break one has to replace the line ...
... aCount = a.Category.find(ctgry => ctgry.Id === id)?.count ?? -1;
... with this alternative ...
... aCount = (a.Category.find(ctgry => ctgry.Id === id) || { count: -1 }).count;
function compareByBoundIdCountOfItemCategoryList(a, b) {
const { id } = this;
const aCount = (
a.Category.find(ctgry => ctgry.Id === id) ||
{ count: -1 }
).count;
const bCount = (
b.Category.find(ctgry => ctgry.Id === id) ||
{ count: -1 }
).count;
// in case of equal counts compare the `Category` array's lengths'.
return (bCount - aCount) || (b.Category.length - a.Category.length);
}
const sampleList = [{
Id: 1,
Info: "Info",
Category: [
{ Id: 2, count: 3 },
{ Id: 4, count: 1 },
{ Id: 8, count: 1 },
{ Id: 18, count: 1 },
{ Id: 9, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 2,
Info: "Info 2",
Category: [
{ Id: 2, count: 3 },
{ Id: 9, count: 2 },
{ Id: 21, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 3,
Info: "Info 3",
Category: [
{ Id: 4, count: 1 },
{ Id: 11, count: 1 },
{ Id: 9, count: 1 },
],
}];
console.log(
'{ id: 9 } ...',
sampleList
.sort(compareByBoundIdCountOfItemCategoryList.bind({ id: 9 }))
);
console.log(
'{ id: 4 } ...',
sampleList
.sort(compareByBoundIdCountOfItemCategoryList.bind({ id: 4 }))
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
I find this format a simpler alternative to the answer from Peter Seliger. We simply store the sought id in a closure when creating the comparator function we pass to sort:
const byCategoryCount = (categoryId) => ({Category: c1}, {Category: c2}) =>
(c2 .find (({Id}) => Id === categoryId) ?.count ?? -1) -
(c1 .find (({Id}) => Id === categoryId) ?.count ?? -1)
const input = [{Id: 1, Info: "Info", Category: [{Id: 2, count: 3}, {Id: 4, count: 1}, {Id: 8, count: 1}, {Id: 18, count: 1}, {Id: 9, count: 1}, {Id: 3, count: 1}]}, {Id: 2, Info: "Info 2", Category: [{Id: 2, count: 3}, {Id: 9, count: 2}, {Id: 21, count: 1}, {Id: 3, count: 1}]}, {Id: 3, Info: "Info 3", Category: [{Id: 4, count: 1}, {Id: 11, count: 1}, {Id: 9, count: 1}]}]
console .log (input .sort (byCategoryCount (9)))
.as-console-wrapper {max-height: 100% !important; top: 0}
If you don't have the nullish coalescing operator available in your environment, this variant is not much worse:
const byCategoryCount = (categoryId) => ({Category: c1}, {Category: c2}) =>
(c2 .find (({Id}) => Id === categoryId) || {count: -1}) .count -
(c1 .find (({Id}) => Id === categoryId) || {count: -1}) .count
We could also choose to write a wrapper function that returns a sorted version without mutating the original list. It might look like this:
const sortByCategoryCount = (categoryId, xs) =>
[... xs] .sort (byCategoryCount (categoryId))
But at that point we might start to wonder whether the helper function is offering us anything and we might choose to refactor to
const sortByCategoryCount = (categoryId, xs) =>
[... xs] .sort (({Category: c1}, {Category: c2}) =>
(c2 .find (({Id}) => Id === categoryId) || {count: -1}).count -
(c1 .find (({Id}) => Id === categoryId) || {count: -1}).count
)
This should work for you sortByCount:
var my_arr = [{
Id: 1,
Info: "Info",
Category: [
{ Id: 2, count: 3 },
{ Id: 4, count: 1 },
{ Id: 8, count: 1 },
{ Id: 18, count: 1 },
{ Id: 9, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 2,
Info: "Info 2",
Category: [
{ Id: 2, count: 3 },
{ Id: 9, count: 2 },
{ Id: 21, count: 1 },
{ Id: 3, count: 1 },
],
}, {
Id: 3,
Info: "Info 3",
Category: [
{ Id: 4, count: 1 },
{ Id: 11, count: 1 },
{ Id: 9, count: 1 },
],
}];
function sortByCount(arr, targetId){
var arr_temp = [];
arr.forEach(el => {
var elem = el.Category.filter(e => e.Id === targetId)[0];
var value = elem ? elem.count : -1;
arr_temp.push({
value: value,
obj: el
});
});
arr_temp.sort((a,b)=> b.value - a.value);
return arr_temp.map(el => el.obj);
}
var sortedArr = sortByCount(my_arr, 9);
console.log(sortedArr)

Count duplicates and order them in array of objects Javascript

I have the following array of objects:
[
{
id: 1,
someOtherStuff: 'abc,
Drink: { name: 'Coca-Cola', price: 2.5 }
},
{
id: 2,
someOtherStuff: 'def,
Drink: { name: 'Fanta Orange', price: 3 }
},
{
id: 3,
someOtherStuff: 'ghi,
Drink: { name: 'Sprite', price: 1.8 }
},
{
id: 6,
someOtherStuff: 'jkl,
Drink: { name: 'Coca-Cola', price: 2.5 }
},
{
id: 7,
someOtherStuff: 'mno,
Drink: { name: 'Coca-Cola', price: 2.5 }
}
]
i want to group them by duplicates like this:
[
{
count: 3,
drinkName: 'Coca-Cola',
price: 2.5
},
{
count: 1,
drinkName: 'Fanta Orange',
price: 3
},
{
count: 1,
drinkName: 'Sprite',
price: 1.8
}
]
I have tried in several ways to map a new array.But unfortunately I can't get it to work
I hope someone can help me with that
let result= {};
inputArray.map((item)=>{
let key = `${item.Drink.name}-${item.Drink.price}`;
if(result[key]){
result[key].count = result[key].count +1;
}else{
result[key] = {count:1,drinkName:item.Drink.name,price:item.Drink.price};
}
});
result = Object.values(result);

Moving data from 2 arrays of objects into a third array

so assume i have 2 arrays of objects...
let orders = [
{ id: 1, itemName: 'Peaches', amount: 2 },
{ id: 2, itemName: 'Mangoes', amount: 1 },
{ id: 3, itemName: 'Mangoes', amount: 10 }
];
let items = [
{ id: 1, name: 'Peaches', qty: 10 },
{ id: 2, name: 'Mangoes', qty: 3 }
];
and i want to find the list of orders for every item and put them in an array called linkedOrders, I tried the below code:
let linkedOrders = _.map(items, item => _.where(orders, { name: item.name }));
console.log(linkedOrders);
This is what I am getting:
[{ id: 1, itemName: 'Peaches', amount: 2 }],
[{ id: 2, itemName: 'Mangoes', amount: 1 },
{ id: 3, itemName: 'Mangoes', amount: 10 }]
but I want something like this:
[{'Peaches': [
{ id: 1, itemName: 'Peaches', amount: 2 }
],
'Mangoes': [
{ id: 2, itemName: 'Mangoes', amount: 1 },
{ id: 3, itemName: 'Mangoes', amount: 10 }
]],
Any help would be appreciated thanks.
You can simply do that using Array reduce method.
const result = items.reduce((result, item) => {
result.push({
[item.name]: orders.filter((order) => order.itemName === item.name)
});
return result;
}, []);
For more information on reduce, check Array​.prototype​.reduce()

Which is the best way to get an array difference from an object?

I have an array of values: ["1", "2", "3"] which contains essentially the reference of the records stored in this array of object:
[
{ id: 1, name: "John" },
{ id: 2, name: "Patrick" },
{ id: 3, name: "Jack" },
{ id: 4, name: "Paula" },
{ id: 5, name: "Sarah" }
]
I would like to return the missing reference from the array of objects, so the result will be: 4, 5. What I achieved so far is takes all the selected values of the first array from all the select available in the html:
var selected_options = $('.options-picker')
.map(function() { return this.value}).get();
this will return 1, 2, 3. How can I extract from the array of objects 4, 5?
Thanks in advance.
Use filter and includes to check the object ids against the values in the array.
const data = [
{ id: 1, name: "John" },
{ id: 2, name: "Patrick" },
{ id: 3, name: "Jack" },
{ id: 4, name: "Paula" },
{ id: 5, name: "Sarah" }
];
const items = [1, 2, 3];
const out = data.filter(obj => !items.includes(obj.id));
console.log(out);
This will do
var a=[
{ id: 1, name: "John" },
{ id: 2, name: "Patrick" },
{ id: 3, name: "Jack" },
{ id: 4, name: "Paula" },
{ id: 5, name: "Sarah" }
]
var b=['1', '2', '3'];
a.forEach((e)=>{
if(b.indexOf(e.id.toString())==-1)
{
b.push(e.id);
}
})
alert(b)

Categories