I am using loadash in my project
i have object in array like this
[{
"rating": {
"time_to_table": 5,
"value_for_money": 5,
"innovation": 5,
"plating_decoration": 5,
"taste": 5
}
}, {
"rating": {
"time_to_table": 0,
"value_for_money": 3,
"innovation": 2,
"plating_decoration": 2,
"taste": 4
}
}]
Now I want output like this by adding each property and want single object like this
"rating": {
"time_to_table": 5,
"value_for_money": 8,
"innovation": 7,
"plating_decoration": 7,
"taste": 9
}
I have tried this
var obj = {
"time_to_table": 0,
"value_for_money": 0,
"innovation": 0,
"plating_decoration": 0,
"taste": 0,
"total" : 5 * data.length
}
_.forEach(data,function(d){
obj.time_to_table += d.rating.time_to_table;
obj.value_for_money += d.rating.value_for_money;
obj.innovation += d.rating.innovation;
obj.plating_decoration += d.rating.plating_decoration;
obj.taste += d.rating.taste;
});
With Lodash you can do this using reduce() and mergeWith() that takes custom function as parameter.
var data = [{"rating":{"time_to_table":5,"value_for_money":5,"innovation":5,"plating_decoration":5,"taste":5}},{"rating":{"time_to_table":0,"value_for_money":3,"innovation":2,"plating_decoration":2,"taste":4}}]
var result = _.reduce(data, function(r, e, i) {
if(i != 0) _.mergeWith(r.rating, e.rating, (a, b) => a + b)
return r;
}, data[0])
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
You can use reduce, and having as many property as you want in your objects.
The following function doesn't require to know anything about the kind of object you are passing, because there are no hardcoded properties
const arr = [{
"rating": {
"time_to_table": 5,
"value_for_money": 5,
"innovation": 5,
"plating_decoration": 5,
"taste": 5
},
a: {b: 1, c: 2}
}, {
"rating": {
"time_to_table": 0,
"value_for_money": 3,
"innovation": 2,
"plating_decoration": 2,
"taste": 4
},
a: {b: 3, c: 0}
}];
const result = arr.reduce(fn, {})
function fn (acc, val) {
for (let x in val) {
acc[x] = acc[x] || {};
for (let y in val[x]) {
acc[x][y] = acc[x][y] || 0;
acc[x][y] += val[x][y];
}
}
return acc;
}
console.log(result)
Array#reduce solution.
var arr = [{"rating":{"time_to_table":5,"value_for_money":5,"innovation":5,"plating_decoration":5,"taste":5}},{"rating":{"time_to_table":0,"value_for_money":3,"innovation":2,"plating_decoration":2,"taste":4}}], obj = arr[0]; arr.splice(0,1);
var res = arr.reduce(function(s, a) {
Object.keys(a.rating).forEach(function(v) {
s.rating[v] += a.rating[v];
})
return s;
}, obj);
console.log(res);
You can do it using Array#reduce() and Object.keys()
const data = [{rating:{time_to_table:5,value_for_money:5,innovation:5,plating_decoration:5,taste:5}},{rating:{time_to_table:0,value_for_money:3,innovation:2,plating_decoration:2,taste:4}}];
let finalObject = data.reduce((o, c) => {
Object.keys(c.rating).forEach(k => {
o.rating[k] = o.rating[k] || 0;
o.rating[k] += c.rating[k];
});
return o;
}, { rating: {} })
console.log(finalObject);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use a recursive approach for arbitrary nested object, to collect and sum values in the objects.
var data = [{ rating: { time_to_table: 5, value_for_money: 5, innovation: 5, plating_decoration: 5, taste: 5 } }, { rating: { time_to_table: 0, value_for_money: 3, innovation: 2, plating_decoration: 2, taste: 4 } }],
result = data.reduce(function iter(target, source) {
Object.keys(source).forEach(function (k) {
if (source[k] && typeof source[k] === 'object') {
iter(target[k] = target[k] || {}, source[k]);
return;
}
target[k] = (target[k] || 0) + +source[k];
});
return target;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
I need to take sum of all the person's ages and heights.
Input Array:
[
{
"personId": 1,
"ages": [
1,
4,
5
],
"heights": [
1,
1,
2
]
},
{
"personId": 2,
"ages": [
4,
2,
2
],
"heights": [
1,
4,
2
]
},
{
"personId": 2,
"ages": [
2,
1,
1
],
"heights": [
12
]
}
]
Desired Output:
[
{
"type": "ages",
"values": 22
},
{
"type": "heights",
"values": 23
}
]
My Solution (Which is working perfectly fine):
var agesTotal = 0;
var heightsTotal = 0;
var resultArr = [];
var sourceArr = [{personId: 1, ages: [1,4,5], heights: [1,1,2]}, {personId: 2, ages: [4,2,2], heights: [1,4,2]}, {personId: 2, ages: [2,1,1], heights: [12]}];
for(var i = 0; i < sourceArr.length; i++){
if(sourceArr[i].ages){
if(i == 0){
resultArr.push({
type: "ages",
values: agesTotal
});
}
for(var n = 0; n < resultArr.length; n++){
if(resultArr[n].type == "ages"){
resultArr[n].values += agesTotal + sourceArr[i].ages.reduce((partialSum, a) => parseFloat(partialSum) + parseFloat(a), 0)
}
}
}
if(sourceArr[i].heights){
if(i == 0){
resultArr.push({
type: "heights",
values: heightsTotal
});
}
for(var n = 0; n < resultArr.length; n++){
if(resultArr[n].type == "heights"){
resultArr[n].values += heightsTotal + sourceArr[i].heights.reduce((partialSum, a) => parseFloat(partialSum) + parseFloat(a), 0)
}
}
}
}
This above code of mine is producing the correct response, but it seems like so much processing and unoptimized.
What I need is the best & optimized possible solution for this operation
Without a clearly defined performance objective, it's hard to provide an answer that I feel is satisfying. However, I think this is readable, concise, and not wasteful:
function sumArrays (accumulator, obj) {
for (const [key, value] of Object.entries(obj)) {
if (!Array.isArray(value)) continue;
accumulator[key] ??= 0;
for (const n of value) accumulator[key] += n;
}
}
function getSums (array) {
const accumulator = {};
for (const obj of array) sumArrays(accumulator, obj);
return Object.entries(accumulator).map(([type, values]) => ({type, values}));
}
// Or, instead, optimized only for the input keys:
function getSumsOptimized (array, keysToSum) {
const result = keysToSum.map(type => ({type, values: 0}));
for (const obj of array) {
for (const [index, key] of keysToSum.entries()) {
for (const n of obj[key]) result[index].values += n;
}
}
return result;
}
const input = [
{ personId: 1, ages: [1, 4, 5], heights: [1, 1, 2]},
{ personId: 2, ages: [4, 2, 2], heights: [1, 4, 2]},
{ personId: 2, ages: [2, 1, 1], heights: [12 ]},
];
console.log(getSums(input));
console.log(getSumsOptimized(input, ['ages', 'heights']));
const array = [
{
"personId": 1,
"ages": [
1,
4,
5
],
"heights": [
1,
1,
2
]
},
{
"personId": 2,
"ages": [
4,
2,
2
],
"heights": [
1,
4,
2
]
},
{
"personId": 2,
"ages": [
2,
1,
1
],
"heights": [
12
]
}
]
let heightsSum = 0;
let agesSum = 0;
array.forEach(element => {
element.ages.forEach(age => {
agesSum += age;
})
element.heights.forEach(height => {
heightsSum += height;
})
})
const arr = [
{
type: 'ages',
values: agesSum
},
{
type: 'heights',
values: heightsSum
}
]
console.log(arr)
I have javascript array object as below. My need is to sum value base on seach id in the array object.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
],
For example sum of value for id 1 is 10 + 30 + 25 + 20 = 85 , It may be something link linq but I'm not sure in javascript. Thanks for all answers.
You can use a combination of filter and reduce to get the result you want:
sumOfId = (id) => array.filter(i => i.id === id).reduce((a, b) => a + b.val, 0);
Usage:
const sumOf1 = sumOfId(1); //85
Reading material:
Array.prototype.filter
Array.prototype.reduce
A way to do it with a traditional for loop
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sums = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
sums[obj.id] = sums[obj.id] === undefined ? 0 : sums[obj.id];
sums[obj.id] += parseInt(obj.val);
}
console.log(sums);
running example
You can use reduce() and findIndex()
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
let res = array.reduce((ac,a) => {
let ind = ac.findIndex(x => x.id === a.id);
ind === -1 ? ac.push(a) : ac[ind].val += a.val;
return ac;
},[])
console.log(res);
JS noob here ... I guess something like this should be here too :-)
let newArray = {}
array.forEach((e) => {
!newArray[e.id] && (newArray[e.id] = 0);
newArray[e.id] += e.val;
});
You can loop on the array and check the ids.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sum = 0;
var id = 1;
$.each(array, function(index, object){
if (object.id == id) {
sum += object.val;
}
});
console.log(sum);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Using Array#reduce and Map you can get the sum for each id like so. This also uses destructuring to have quicker access to properties.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
console.log(res.get(1));
console.log(res.get(2));
If you wanted to output all the sums, then you need to use Array#from
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
);
console.log(res);
If the format should be similar as to your original structure, you need to add a Array#map afterwards to transform it.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
).map(([id,sum])=>({id,sum}));
console.log(res);
You could take GroupBy from linq.js with a summing function.
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }],
result = Enumerable
.From(array)
.GroupBy(null, null, "{ id: $.id, sum: $$.Sum('$.val') }", "$.id")
.ToArray();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
Here is another option, introducing an Array.prototype.sum helper:
Array.prototype.sum = function (init = 0, fn = obj => obj) {
if (typeof init === 'function') {
fn = init;
init = 0;
}
return this.reduce(
(acc, ...fnArgs) => acc + fn(...fnArgs),
init
);
};
// .sum usage examples
console.log(
// sum simple values
[1, 2, 3].sum(),
// sum simple values with initial value
[1, 2, 3].sum(10),
// sum objects
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(obj => obj.a),
// sum objects with initial value
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(10, obj => obj.a),
// sum custom combinations
[{ amount: 1, price: 2 }, { amount: 3, price: 4 }]
.sum(product => product.amount * product.price)
);
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }];
// solutions
console.log(
array.filter(obj => obj.id === 1).sum(obj => obj.val),
array.filter(({id}) => id === 1).sum(({val}) => val),
array.sum(({id, val}) => id === 1 ? val : 0)
);
references:
Array.prototype.reduce
Array.prototype.filter
Arrow functions used in sum(obj => obj.val)
Object destructing assignment used in ({id}) => id === 1
Rest parameters used in (acc, ...fnArgs) => acc + fn(...fnArgs)
Conditional (ternary) operator used in id === 1 ? val : 0
Let's say, I have an Array of object which looks like:
var jsonData = [
{"DS01":123,"DS02":88888,"DS03":1,"DS04":2,"DS05":3,"DS06":666},
{"DS01":123,"DS02":88888,"DS03":2,"DS04":3,"DS05":4,"DS06":666},
{"DS01":124,"DS02":99999,"DS03":3,"DS04":4,"DS05":5,"DS06":333},
{"DS01":124,"DS02":99999,"DS03":5,"DS04":6,"DS05":7,"DS06":333}
];
You can see there are some common key fields which are DS01, DS02 and DS06. Firstly, I want to find which are common group of keys.
For first 2 Objects : DS01 = 123, DS02 = 88888, DS06 = 666
For last 2 Objects : DS01 = 124, DS02 = 99999, DS06 = 333
I want to convert this array of objects to a format like this:
var jsonDataReduced =
[{
"DS01": 123,
"DS02": 88888,
"DS03": [1, 2],
"DS04": [2, 3],
"DS05": [3, 4],
"DS06": 666
},
{
"DS01": 124,
"DS02": 99999,
"DS03": [3, 5],
"DS04": [4, 6],
"DS05": [5, 7],
"DS06": 333
}
];
Let's say, I have another array of objects.
var jsonData2 = [{
"Mass": 3,
"Force": 3.1,
"Acceleration": 4
}, {
"Mass": 3,
"Force": 4.1,
"Acceleration": 4
}];
So after reducing it should be:
var jsonData2 = [{
"Mass": 3,
"Force": [3.1, 4.1],
"Acceleration": 4
}];
I have been trying to do these by using Array.reduce() but not getting an idea on how to do this job efficiently.
Is it possible to
making a single function
passing these kinds of array of objects as a parameter
and finally getting the reduced dataset
What I have tried :
var jsonData2 = [{
"Mass": 3,
"Force": 3.1,
"Acceleration": 4
}, {
"Mass": 3,
"Force": 4.1,
"Acceleration": 4
}];
const reduced = jsonData2.reduce((r, e, i, a) => {
if (i % 2 == 0) {
const next = a[i + 1];
const obj = { ...e, Force: [e.Force] }
if (next) obj.Force.push(next.Force);
r.push(obj)
}
return r;
}, []);
console.log(reduced);
You could get common keys and group by them.
var data = [{ DS01: 123, DS02: 88888, DS03: 1, DS04: 2, DS05: 3, DS06: 666 }, { DS01: 123, DS02: 88888, DS03: 2, DS04: 3, DS05: 4, DS06: 666 }, { DS01: 124, DS02: 99999, DS03: 3, DS04: 4, DS05: 5, DS06: 333 }, { DS01: 124, DS02: 99999, DS03: 5, DS04: 6, DS05: 7, DS06: 333 }],
common,
temp = data.reduce((r, o, i) => {
Object.entries(o).forEach(([k, v]) => {
r[k] = r[k] || [];
r[k][i] = v;
});
return r;
}, {}),
min = Infinity,
result;
Object.entries(temp).forEach(([k, a]) => {
var s = new Set;
temp[k] = a.map(v => s.add(v).size);
min = Math.min(min, s.size);
});
common = Object.keys(temp).filter(k => temp[k][temp[k].length - 1] === min);
result = data.reduce((r, o) => {
var temp = r.find(q => common.every(k => q[k] === o[k]));
if (!temp) {
r.push({ ...o });
} else {
Object.keys(o).filter(k => !common.includes(k)).forEach(k => Array.isArray(temp[k]) ? temp[k].push(o[k]) : (temp[k] = [temp[k], o[k]]));
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have javascript array object as below. My need is to sum value base on seach id in the array object.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
],
For example sum of value for id 1 is 10 + 30 + 25 + 20 = 85 , It may be something link linq but I'm not sure in javascript. Thanks for all answers.
You can use a combination of filter and reduce to get the result you want:
sumOfId = (id) => array.filter(i => i.id === id).reduce((a, b) => a + b.val, 0);
Usage:
const sumOf1 = sumOfId(1); //85
Reading material:
Array.prototype.filter
Array.prototype.reduce
A way to do it with a traditional for loop
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sums = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
sums[obj.id] = sums[obj.id] === undefined ? 0 : sums[obj.id];
sums[obj.id] += parseInt(obj.val);
}
console.log(sums);
running example
You can use reduce() and findIndex()
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
let res = array.reduce((ac,a) => {
let ind = ac.findIndex(x => x.id === a.id);
ind === -1 ? ac.push(a) : ac[ind].val += a.val;
return ac;
},[])
console.log(res);
JS noob here ... I guess something like this should be here too :-)
let newArray = {}
array.forEach((e) => {
!newArray[e.id] && (newArray[e.id] = 0);
newArray[e.id] += e.val;
});
You can loop on the array and check the ids.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sum = 0;
var id = 1;
$.each(array, function(index, object){
if (object.id == id) {
sum += object.val;
}
});
console.log(sum);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Using Array#reduce and Map you can get the sum for each id like so. This also uses destructuring to have quicker access to properties.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
console.log(res.get(1));
console.log(res.get(2));
If you wanted to output all the sums, then you need to use Array#from
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
);
console.log(res);
If the format should be similar as to your original structure, you need to add a Array#map afterwards to transform it.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
).map(([id,sum])=>({id,sum}));
console.log(res);
You could take GroupBy from linq.js with a summing function.
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }],
result = Enumerable
.From(array)
.GroupBy(null, null, "{ id: $.id, sum: $$.Sum('$.val') }", "$.id")
.ToArray();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
Here is another option, introducing an Array.prototype.sum helper:
Array.prototype.sum = function (init = 0, fn = obj => obj) {
if (typeof init === 'function') {
fn = init;
init = 0;
}
return this.reduce(
(acc, ...fnArgs) => acc + fn(...fnArgs),
init
);
};
// .sum usage examples
console.log(
// sum simple values
[1, 2, 3].sum(),
// sum simple values with initial value
[1, 2, 3].sum(10),
// sum objects
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(obj => obj.a),
// sum objects with initial value
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(10, obj => obj.a),
// sum custom combinations
[{ amount: 1, price: 2 }, { amount: 3, price: 4 }]
.sum(product => product.amount * product.price)
);
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }];
// solutions
console.log(
array.filter(obj => obj.id === 1).sum(obj => obj.val),
array.filter(({id}) => id === 1).sum(({val}) => val),
array.sum(({id, val}) => id === 1 ? val : 0)
);
references:
Array.prototype.reduce
Array.prototype.filter
Arrow functions used in sum(obj => obj.val)
Object destructing assignment used in ({id}) => id === 1
Rest parameters used in (acc, ...fnArgs) => acc + fn(...fnArgs)
Conditional (ternary) operator used in id === 1 ? val : 0
I have an array:
let ar = [{
asst: 1,
v: 'b'
}, {
emp: 4
}, {
journal_id: 3
}, {
asst: 4
}, {
asst: 1,
v: 'a'
}, {
asst: 1,
v: 'c'
}, {
journal_id: 3
}, {
journal_id: 3
}]
I want an array that has asst and journal_id as array of arrays and emp as just an object in the array that has array of asst and journal_id.
Like this:
[[{asst:1, v: 'a'}, {asst:1, v: 'b'},{asst:1, v: 'c'}], [{asst:4}], [{journal_id:3}, {journal_id:3}, {journal_id:3}], {emp:4}]
I have tried this:
let ar = [{
asst: 1,
v: 'b'
}, {
emp: 4
}, {
journal_id: 3
}, {
asst: 4
}, {
asst: 1,
v: 'a'
}, {
asst: 1,
v: 'c'
}, {
journal_id: 3
}, {
journal_id: 3
}]
let asstArray = [],
journalArray = [],
fullArray = [];
for (let i = 0; i < ar.length; i++) {
debugger
if (ar[i].asst) {
let contains = false;
for (let j = 0; j < asstArray.length; j++) {
for (let k = 0; k < asstArray[j].length; k++) {
if (asstArray[j][k].asst == ar[i].asst) {
contains = true;
let d = asstArray[j][k];
}
}
if (contains) {
asstArray[j].push(ar[i]);
}
}
if (!contains) {
asstArray.push([ar[i]]);
}
} else if (ar[i].journal_id) {
let contains = false;
for (let j = 0; j < journalArray.length; j++) {
for (let k = 0; k < journalArray[j].length; k++) {
if (journalArray[j][k].journal_id == ar[i].journal_id) {
contains = true;
}
}
if (contains) {
journalArray[j].push(ar[i]);
}
}
if (!contains) {
journalArray.push([ar[i]]);
}
}
}
fullArray.push(asstArray);
fullArray.push(journalArray);
console.log(fullArray, "Full")
JS Fiddle
Here is a succint way to do it with reduce and Object.values. Also, the keys to check are declared in the initial value to the reduce function.
By using ES6 desctructuring, you can then rebuild the array you want at the end, with emp, out of the inner arrays.
With emp in the array:
const ar = [
{ asst: 1, v: 'b' },
{ emp: 4 },
{ journal_id: 3 },
{ asst: 4 },
{ asst: 1, v: 'a' },
{ asst: 1, v: 'c' },
{ journal_id: 3 },
{ journal_id: 3 }
];
const result = Object.values(ar.reduce((accum, e) => {
Object.keys(accum).forEach(k => {
if (k in e) accum[k].push(e);
});
return accum;
}, { asst: [], journal_id: [], emp: [] }));
console.log(result);
With emp outside the inner array:
const ar = [
{ asst: 1, v: 'b' },
{ emp: 4 },
{ journal_id: 3 },
{ asst: 4 },
{ asst: 1, v: 'a' },
{ asst: 1, v: 'c' },
{ journal_id: 3 },
{ journal_id: 3 }
];
let result = ar.reduce((accum, e) => {
Object.keys(accum).forEach(k => {
if (k in e) accum[k].push(e);
});
return accum;
}, { asst: [], journal_id: [], emp: [] });
const { emp, ...otherProps } = result;
result = [...Object.values(otherProps), emp[0]];
console.log(result);
You could combine the values of the wanted grouping keys to a single key and group by this value.
Objects without grouping keys are pushed to the result set directly.
var array = [{ asst: 1, v: 'b' }, { emp: 4 }, { journal_id: 3 }, { asst: 4 }, { asst: 1, v: 'a' }, { asst: 1, v: 'c' }, { journal_id: 3 }, { journal_id: 3 }], keys = ['asst', 'journal_id'],
keys = ['asst', 'journal_id'],
result = array.reduce((hash => (r, o) => {
if (keys.some(k => k in o)) {
var key = keys.map(k => o[k]).join('|');
if (!hash[key]) {
r.push(hash[key] = []);
}
hash[key].push(o);
} else {
r.push(o);
}
return r;
})({}), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can reduce the array in a Map and then create a new array with the Map values:
const data = [{"asst":1,"v":"b"},{"emp":4},{"journal_id":3},{"asst":4},{"asst":1,"v":"a"},{"asst":1,"v":"c"},{"journal_id":3},{"journal_id":3}];
const grouped = data.reduce(
(result,item)=>{
//key is item.asst or item.jornal_id or other
const key = item.asst || item.journal_id || 'other';
//set result(key) with empty array or existing array and conat new item
return result.set(key,(result.get(key)||[]).concat(item));
},new Map()
);
//get other values or empty array if they don't exist:
const others = grouped.get('other') || [];
//remove others if they exist:
grouped.delete('other');
//log array from Map values
console.log(others.concat([...grouped.values()]));