This is the input array of object:
var array = [{
id: 1,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 2,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:50.000Z'
},
{
id: 3,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:34:30.000Z'
},
{
id: 4,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:36:00.000Z'
},
{
id: 5,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 6,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z'
}
]
I want to group it like this as output:
var output = [
[{
id: 1,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 2,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:50.000Z'
},
{
id: 3,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:34:30.000Z'
},
{
id: 4,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:36:00.000Z'
}
],
[{
id: 5,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 6,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z'
}
]
]
As you can see, only id and time
, are unique, and I want to group it based on duplicatesname, family, number and category
, So all objects which have the same value for name, family, number and category
should have a separate array.
I have tried a lot of things, I used two nested for loop, I used map, I sued Filter, ... I tried all I could think of, but I was not able to do it!
If anyone can help one this, I really appreciate it.
This is the input array of object:
var array = [{
id: 1,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 2,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:50.000Z'
},
{
id: 3,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:34:30.000Z'
},
{
id: 4,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:36:00.000Z'
},
{
id: 5,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 6,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z'
}
]
I want to group it like this as output:
var output = [
[{
id: 1,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 2,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:50.000Z'
},
{
id: 3,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:34:30.000Z'
},
{
id: 4,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:36:00.000Z'
}
],
[{
id: 5,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 6,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z'
}
]
]
As you can see, only id and time
, are unique, and I want to group it based on duplicatesname, family, number and category
, So all objects which have the same value for name, family, number and category
should have a separate array.
I have tried a lot of things, I used two nested for loop, I used map, I sued Filter, ... I tried all I could think of, but I was not able to do it!
If anyone can help one this, I really appreciate it.
Share Improve this question edited Jul 22, 2018 at 14:24 Rick 4,1249 gold badges27 silver badges37 bronze badges asked Jul 21, 2018 at 8:18 Emad DehnaviEmad Dehnavi 3,4515 gold badges23 silver badges47 bronze badges 1- 1 Show us any code because now this question sounds like "do it for me". – An0num0us Commented Jul 21, 2018 at 8:23
3 Answers
Reset to default 4You could take a Map
and collect all items of the same group in an array.
Later get only the values of the map as result.
This is only for one one group category
.
var array = [{ id: 1, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:00.000Z' }, { id: 2, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:50.000Z' }, { id: 3, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:34:30.000Z' }, { id: 4, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:36:00.000Z' }, { id: 5, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' }, { id: 6, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' }],
grouped = Array.from(array.reduce((m, o) =>
m.set(o.category, (m.get(o.category) || []).concat(o)), new Map).values());
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For more than one group, you could take a joined key with the values of the actual object of name
, family
, number
and category
in a closure for key
.
Then map new arrays with close times and bine all arrays to single nested arrays. At the end filter by length.
var array = [{ id: 1, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:33:00.000Z" }, { id: 2, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:33:50.000Z" }, { id: 3, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:34:30.000Z" }, { id: 4, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:36:00.000Z" }, { id: 5, sourceAccount: "A", targetAccount: "C", amount: 250, category: "other", time: "2018-03-02T10:33:00.000Z" }, { id: 6, sourceAccount: "A", targetAccount: "C", amount: 250, category: "other", time: "2018-03-02T10:33:05.000Z" }],
groupBy = ['name', 'family', 'number', 'category'],
result = Array
.from(
array
.reduce((m, o) => (k => m.set(k, (m.get(k) || []).concat(o)))(groupBy.map(k => o[k]).join('|')), new Map)
.values(),
o => o.sort((a, b) => a.time.localeCompare(b.time))
)
.map(g => g.reduce((r, o, i, a) => {
if (!i || new Date(o.time).getTime() - new Date(a[i - 1].time).getTime() > 60000) {
r.push([o]);
} else {
r[r.length - 1].push(o);
}
return r;
}, []))
.reduce((r, a) => r.concat(a), [])
.filter(a => a.length > 1);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Simply make a map using Array.reduce() with a bined key of name, family,number and category
. And than you can use Object.values() on that map to get the desired result.
var array =[ { id: 1, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:00.000Z' }, { id: 2, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:50.000Z' }, { id: 3, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:34:30.000Z' }, { id: 4, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:36:00.000Z' }, { id: 5, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' }, { id: 6, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' } ];
var result = Object.values(array.reduce((a,curr)=>{
const {name, family, number, category} = curr;
const key = `${name}_${family}_${number}_${category}`;
(a[key] = a[key] || []).push(curr);
return a;
},{}));
console.log(result);
You can also use Array.reduce()
to get that output:
var array = [ { id: 1,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:00.000Z' },
{ id: 2,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:33:50.000Z' },
{ id: 3,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:34:30.000Z' },
{ id: 4,
name: 'A',
family: 'B',
number: 100,
category: 'test',
time: '2018-03-02T10:36:00.000Z' },
{ id: 5,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z' },
{ id: 6,
name: 'A',
family: 'C',
number: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z' }
];
var res = array.reduce((acc, obj)=>{
var existObj;
for(var i = 0 ; i < acc.length; i++) {
let accArray = acc[i];
if(accArray){
existObj = accArray.find(({name, family, number, category}) => name == obj.name && family == obj.family && number == obj.number && category == obj.category);
if(existObj) {
accArray.push(obj);
return acc;
}
}
}
acc.push([obj]);
return acc;
}, []);
console.log(res);