Grouping array of objects by multiple properties - javascript

I have an array of notifications that I want to group by certain conditions (like facebook's notifications)
var data = [
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1, ... }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' },
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1, ... }, read_at: '2021-03-29 15:14:21', created_at: '2021-03-28 08:11:50' },
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6, ... }, read_at: null, created_at: '2021-07-24 08:34:25' },
]
Let's say I want to group by date in descending order
So I have this code:
function sortByDate(array, desc = true) {
if (desc === false) {
// Ascending order
return array.sort((a, b) => {
if (new Date(a.created_at) > new Date(b.created_at)) {
return 1
} else {
return -1
}
return 0
})
}
// Descending order
return array.sort((a, b) => {
if (new Date(a.created_at) < new Date(b.created_at)) {
return 1
} else {
return -1
}
return 0
})
}
So now we have array like this:
[
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6, ... }, read_at: null, created_at: '2021-07-24 08:34:25' },
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1, ... }, read_at: '2021-03-29 15:14:21', created_at: '2021-03-28 08:11:50' },
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1, ... }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' },
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' },
]
Now that our array is sorted, I created a function:
// https://www.tutorialspoint.com/most-efficient-method-to-groupby-on-an-array-of-objects-in-javascript
function groupByProperty(array, property) {
return array.reduce((acc, object) => {
const key = object[property]
if (! acc[key]) {
acc[key] = []
}
acc[key].push(object)
return acc
}, {})
}
Then, I run this code
Object.values(groupByProperty(data, 'type'))
Which return:
[
[
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6, ... }, read_at: null, created_at: '2021-07-24 08:34:25' }
],
[
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' }
],
[
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1, ... }, read_at: '2021-03-29 15:14:21', created_at: '2021-03-28 08:11:50' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1, ... }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' }
],
[
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1, ... }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' }
],
]
I want to group these notifications by these categories:
Same type (I already covered this in my function groupByProperty())
Same in: { id: ... } Except for type: shop.follower
If #1 and #2 were true, check for similar objects with created_at: ... date interval between 10 minutes
If we have a case like #3 (multiple), if one among it has read_at = null, then it will be an unread notification, get the latest (newest) date
In id: 4 and id: 5, interval between timestamp are less than 10 minutes, so I want it to group as one
example EXPECTED OUTPUT:
[
[
{ by: {id: 4, name: "User D"}, created_at: "2021-07-24 08:34:25", id: 8, in: {id: 6}, read_at: null, type: "comment.replied" }
],
[
{ by: {id: 3, name: "User C"}, created_at: "2021-07-18 10:31:12", id: 7, in: null, read_at: null, type: "shop.follower" }
],
[
{ by: {id: 5, name: "User E"}, created_at: "2021-05-23 10:02:21", id: 6, in: null, read_at: null, type: "shop.follower" }
],
[
{ by: {id: 3, name: "User C"}, created_at: "2021-03-28 08:12:24", id: 5, in: {id: 1}, read_at: null, type: "product.liked" },
{ by: {id: 4, name: "User D"}, created_at: "2021-03-28 08:11:50", id: 4, in: {id: 1}, read_at: "2021-03-29 15:14:21", type: "product.liked" }
],
[
{ by: {id: 3, name: "User C"}, created_at: "2021-02-19 16:21:43", id: 3, in: {id: 1}, read_at: "2021-02-20 20:01:39", type: "product.commented" }
],
[
{ by: {id: 2, name: "User B"}, created_at: "2020-08-02 05:24:45", id: 2, in: {id: 1}, read_at: "2021-01-03 10:15:43", type: "product.liked" }
],
[
{ by: {id: 2, name: "User B"}, created_at: "2020-08-02 05:21:20", id: 1, in: null, read_at: "2021-01-03 10:15:43", type: "shop.follower" }
],
]
example IN BROWSER:
|------------------------------------------------------------------------------|
| - (UNREAD) User D replied to your comment ....., 2021-07-24 08:34:25 |
| - (UNREAD) User C start follow your shops ....., 2021-07-18 10:31:12 |
| - (UNREAD) User E start follow your shops ....., 2021-05-23 10:02:21 |
| - (UNREAD) User C and D liked your product ....., 2021-03-28 08:12:24 | <= (Please pay attention)
| - (READ) User C commented on your product ....., 2021-02-19 16:21:43 |
| - (READ) User B liked your product ....., 2020-08-02 05:24:45 |
| - (READ) User B start follow your shops ....., 2020-08-02 05:21:20 |
This is the code I tried to find interval between 10 minutes
function inRangeBetween(val, min, max) {
if (val >= min && val <= max) {
return true
}
return false
}
var startingPoint = { min: 0, max: 0, type: null },
newData = []
for (var i = 0; i < data.length; i++) {
if (startingPoint.min < 1
&& startingPoint.max < 1
&& startingPoint.type === null) {
console.log('Starting point')
var start = new Date(data[i].created_at)
startingPoint.min = start.getTime()
startingPoint.max = start.getTime() + (10 * 60000)
startingPoint.type = data[i].type
newData[data[i].type] = []
} else {
// startingPoint has values
if (inRangeBetween(new Date(data[i].created_at).getTime(), startingPoint.min, startingPoint.max
&& data[i].type === startingPoint.type) {
console.log(`Pushing new object to key ${data[i].type}`)
newData[data[i].type].push(data[i])
} else {
// Set new values for startingPoint, and start again comparing
console.log('Starting point values changes')
startingPoint.min = new Date(data[i]).getTime()
startingPoint.min = new Date(data[i]).getTime() + (10 * 60000)
startingPoint.type = data[i].type
newData[data[i].type] = []
newData[data[i].type].push(data[i])
}
}
}
// Not working
How to achieve this? (Stuck in this problem for 5 days)
Thanks in advance

Try like this:
var data = [
{ id: 1, type: 'shop.follower', by: { id: 2, name: 'User B', }, in: null, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:21:20' },
{ id: 2, type: 'product.liked', by: { id: 2, name: 'User B' }, in: { id: 1 }, read_at: '2021-01-03 10:15:43', created_at: '2020-08-02 05:24:45' },
{ id: 3, type: 'product.commented', by: { id: 3, name: 'User C' }, in: { id: 1 }, read_at: '2021-02-20 20:01:39', created_at: '2021-02-19 16:21:43' },
{ id: 4, type: 'product.liked', by: { id: 4, name: 'User D' }, in: { id: 1 }, read_at: '2021-01-03 10:15:43', created_at: '2021-03-28 08:11:50' },
{ id: 5, type: 'product.liked', by: { id: 3, name: 'User C' }, in: { id: 1 }, read_at: null, created_at: '2021-03-28 08:12:24' },
{ id: 6, type: 'shop.follower', by: { id: 5, name: 'User E' }, in: null, read_at: null, created_at: '2021-05-23 10:02:21' },
{ id: 7, type: 'shop.follower', by: { id: 3, name: 'User C' }, in: null, read_at: null, created_at: '2021-07-18 10:31:12' },
{ id: 8, type: 'comment.replied', by: { id: 4, name: 'User D' }, in: { id: 6 }, read_at: null, created_at: '2021-07-24 08:34:25' }
]
function sortByDate(array, desc = true) {
if (desc === false) {
// Ascending order
return array.sort((a, b) => {
if (new Date(a.created_at) > new Date(b.created_at)) {
return 1
} else {
return -1
}
return 0
})
}
// Descending order
return array.sort((a, b) => {
if (new Date(a.created_at) < new Date(b.created_at)) {
return 1
} else {
return -1
}
return 0
})
}
function groupByProperties(array, properties) {
return Object.values(array.reduce((acc, object) => {
const key = properties.reduce((acc, property) => {
return acc + (object[property] ? JSON.stringify(object[property]) : '')
}, '')
if (! acc[key]) {
acc[key] = []
}
acc[key].push(object)
return acc
}, {}))
}
function groupByInterval(data, interval) {
var group;
for(var i = 0; i < data.length; i++) {
if(1 < data[i].length) {
var max_date = new Date(data[i][0].created_at);
for(var j = data[i].length - 1; 0 < j; j--) {
var next_date = new Date(data[i][j].created_at)
if(interval < max_date - next_date) {
if(!group) {
group = i + 1;
data.splice(group, 0, [])
}
data[group].splice(0, 0, data[i][j])
data[i].splice(j, 1)
};
};
if(group) {
return groupByInterval(data, interval)
};
}
data[i].sort((a, b) => {
if(!a.read_at) {
return -1
}
if(!b.read_at) {
return 1
}
return 0
})
}
data.sort((a, b) => new Date(b[0].created_at) - new Date(a[0].created_at))
return data
}
sortByDate(data)
//1. Same type
//2. Same in: { id: ... } (Except for type: shop.follower)
data = groupByProperties(data, ['type', 'in'])
//3. If #1 and #2 true, check for similar objects with created_at: ... date gap between 10 minutes
//4. If we have a case like #3 (multiple), if one among it has read_at = null, then it unread notification, then get the latest (newest) date
data = groupByInterval(data, 1000 * 60 * 10) //10min
console.log(data)
groupByProperties() is based on groupByProperty(), but accepts multiple properties for grouping (categories 1 and 2). It checks whether the value of the property is falsy (such as null), excluding it from grouping criteria if so.
groupByInterval() added to separate groups according to a specified interval in milliseconds (categories 3 and 4). It then sorts the groups according to read_at being falsy, so that objects with read_at == null appear first in each group. It then sorts across groups to achieve the order in the expected result.

Mr.sbgib is absolutely correct, but i just modified sortByDate function to a little short as follows to reduce duplicate codes,
function sortByDate(array, desc = true) {
return array.sort((a, b) => {
var compare = new Date(a.created_at) < new Date(b.created_at);
return (desc == true) ? ((compare == true) ? 1 : -1) : ((compare == false) ? 1 : -1);
})
}

Related

Loop through map and push to a new object group if items have matching values [duplicate]

This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 17 days ago.
I have the following data structure in its simplest form:
items: [
{ id: 1, account: 'acct_101' },
{ id: 2, account: 'acct_52' },
{ id: 3, account: 'acct_33' },
{ id: 4, account: 'acct_101' },
{ id: 5, account: 'acct_101' },
]
I would like to separate the items into groups based on their account data. The data is dynamic; I don't know in advance what the account numbers may be.
I can loop through the data:
items.map((item) => (
console.log("item account: ", item.account)
))
Yet unsure how to match if an item.account already exists and if so add to an existing data object, if not create a new object group.
The desired output could like like this:
item_groups: [
{
acct_101: [
{ id: 1, account: 'acct_101' },
{ id: 4, account: 'acct_101' },
{ id: 5, account: 'acct_101' },
],
acct_52: [
{ id: 2, account: 'acct_52' },
],
acct_33: [
{ id: 2, account: 'acct_33' },
],
}
]
Try like below:
const items = [
{ id: 1, account: 'acct_101' },
{ id: 2, account: 'acct_52' },
{ id: 3, account: 'acct_33' },
{ id: 4, account: 'acct_101' },
{ id: 5, account: 'acct_101' },
]
const output = items.reduce((prev, curr) => {
if(prev[curr.account]) {
prev[curr.account].push(curr)
} else {
prev[curr.account] = [curr]
}
return prev
}, {})
console.log([output])
More shorter form:
const items = [
{ id: 1, account: 'acct_101' },
{ id: 2, account: 'acct_52' },
{ id: 3, account: 'acct_33' },
{ id: 4, account: 'acct_101' },
{ id: 5, account: 'acct_101' },
]
const output = items.reduce((prev, curr) => {
prev[curr.account] = (prev[curr.account] ?? []).concat(curr)
return prev
}, {})
console.log([output])
Using Array.prototype.reduce()
For your desired output I think you need to use reduce higher order function.
So your code will be :
const itemGroups = items.reduce((acc, item) => {
const account = item.account;
if (acc[account]) {
acc[account].push(item);
} else {
acc[account] = [item];
}
return acc;
}, {});
console.log(itemGroups);
Output :
{
acct_101: [
{ id: 1, account: 'acct_101' },
{ id: 4, account: 'acct_101' },
{ id: 5, account: 'acct_101' }
],
acct_52: [ { id: 2, account: 'acct_52' } ],
acct_33: [ { id: 3, account: 'acct_33' } ]
}
const arr = [{
id: 1,
account: 'acct_101'
},
{
id: 2,
account: 'acct_52'
},
{
id: 3,
account: 'acct_33'
},
{
id: 4,
account: 'acct_101'
},
{
id: 5,
account: 'acct_101'
},
];
const retObj = {};
for (let i = 0; i < arr.length; i++) {
retObj[arr[i]["account"]] = arr.filter(item => item.account == arr[i]["account"]);
}
console.log(retObj)

Filter the object based on the nested array object

Recently, I gave an interview and rejected there were about 10 questions. Each question had 60 seconds. There was a question that went wrong but I was curious why it happened.
I have to filter those objects in which given SearchValue match with the list array object name property. The search value was already given.
For example:
const SearchValue = 'event';
It is filtered array because list[0].name property value match with the the event text.
const res = [
{
id: 2,
name: 'Events',
list: [
{
id: 1,
name: 'Event Ticketing System',
slug: '/'
},
{
id: 2,
name: 'Events Management Software',
slug: '/'
}
]
}
];
The name property contains value something like this Online Translation Services and Spelling and Grammar Check etc. If the search value match with the text then save it those filtered objects and console.log. The data-set was something like this.
const listing = [
{
id: 1,
name: 'Language',
list: [
{
id: 1,
name: 'Online Translation Services',
slug: '/'
},
{
id: 2,
name: 'Spelling and Grammar Check',
slug: '/'
},
{
id: 3,
name: 'TEFL Courses',
slug: '/'
},
{
id: 4,
name: 'Language Learning',
slug: '/'
}
]
},
{
id: 2,
name: 'Events',
list: [
{
id: 1,
name: 'Event Ticketing System',
slug: '/'
},
{
id: 2,
name: 'Events Management Software',
slug: '/'
}
]
}
];
My implementation was this.
const SearchValue = 'event';
const listing = [{
id: 1,
name: 'Language',
list: [{
id: 1,
name: 'Online Translation Services',
slug: '/'
},
{
id: 2,
name: 'Spelling and Grammar Check',
slug: '/'
},
{
id: 3,
name: 'TEFL Courses',
slug: '/'
},
{
id: 4,
name: 'Language Learning',
slug: '/'
}
]
},
{
id: 2,
name: 'Events',
list: [{
id: 1,
name: 'Event Ticketing System',
slug: '/'
},
{
id: 2,
name: 'Events Management Software',
slug: '/'
}
]
}
];
const res = listing.filter(object => {
if (Array.isArray(object.list) && object.list.length > 0) {
return object.list.filter((item) => {
return item.name.toLowerCase().indexOf(SearchValue.toLowerCase()) !== -1;
});
}
});
console.log('Result Array', res);
If anyone can provide a good solution really appreciated. I also want to know What was wrong with this logic?
You can use Array#filter along with Array#some to verify if any of the elements of the list property of each object contains the search text in its name.
const listing = [ { id: 1, name: 'Language', list: [ { id: 1, name: 'Online Translation Services', slug: '/' }, { id: 2, name: 'Spelling and Grammar Check', slug: '/' }, { id: 3, name: 'TEFL Courses', slug: '/' }, { id: 4, name: 'Language Learning', slug: '/' } ] }, { id: 2, name: 'Events', list: [ { id: 1, name: 'Event Ticketing System', slug: '/' }, { id: 2, name: 'Events Management Software', slug: '/' } ] } ];
const SearchValue = 'event';
const res = listing.filter(({list})=>
list.some(({name})=>name.toLowerCase().includes(SearchValue.toLowerCase())));
console.log(res);
Check with RegEx and test
const SearchValue = 'event';
const listing = [{
id: 1,
name: 'Language',
list: [{
id: 1,
name: 'Online Translation Services',
slug: '/'
},
{
id: 2,
name: 'Spelling and Grammar Check',
slug: '/'
},
{
id: 3,
name: 'TEFL Courses',
slug: '/'
},
{
id: 4,
name: 'Language Learning',
slug: '/'
}
]
},
{
id: 2,
name: 'Events',
list: [{
id: 1,
name: 'Event Ticketing System',
slug: '/'
},
{
id: 2,
name: 'Events Management Software',
slug: '/'
}
]
}
];
const res = listing.filter(object => {
if (Array.isArray(object.list) && object.list.length > 0) {
// Check items with RegEx test
// and update object.list
object.list = object.list.filter(item => new RegExp(SearchValue, 'i').test(item.name));
// Return true if list length > 0
if(object.list.length > 0) return true;
}
});
console.log('Result Array', res);
Array Filter
let newArray = arr.filter(callback(element[, index, [array]])[, thisArg])
callback
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise.
Return value
A new array with the elements that pass the test. If no elements pass the test, an empty array will be returned.
const SearchValue = 'language';
const listing = [{
id: 1,
name: 'Language',
list: [{
id: 1,
name: 'Online Translation Services',
slug: '/'
},
{
id: 2,
name: 'Spelling and Grammar Check',
slug: '/'
},
{
id: 3,
name: 'TEFL Courses',
slug: '/'
},
{
id: 4,
name: 'Language Learning',
slug: '/'
}
]
},
{
id: 2,
name: 'Events',
list: [{
id: 1,
name: 'Event Ticketing System',
slug: '/'
},
{
id: 2,
name: 'Events Management Software',
slug: '/'
}
]
}
];
const res = listing.reduce((pre, object) => {
if(!Array.isArray(object.list) || object.list.length <= 0)
return pre
object.list = object.list.filter((item) => item.name.toLowerCase().indexOf(SearchValue.toLowerCase()) > -1);
return object.list.length > 0 ? [...pre, object] : pre;
}, []);
console.log('Result Array', res);

Transform Nested Object Data Structure into an Array of Objects- JavaScript

I am having trouble with this problem taking an object and reformatting it to a new data structure. I need to take the beginning object and do the following: sort by group first, then label and exclude "active: false" records.
var beginning = {
Sister: {
1: { id: 1, name: 'Jesse Steven', active: false },
2: { id: 2, name: 'Zena Wong', active: true },
3: { id: 3, name: 'Katie Johnson', active: true },
},
Brother: {
10: { id: 10, name: 'Jeff Jacobs', active: true },
11: { id: 11, name: 'Mark Matha', active: false },
12: { id: 12, name: 'Kyle Ford', active: true },
},
Friend: {
20: { id: 20, name: 'Jim Dobbs', active: true },
}
};
After, it should looks like this:
var final = [
{ label: 'Jeff Jacobs', value: 10, group: 'Brother' },
{ label: 'Kyle Ford', value: 12, group: 'Brother' },
{ label: 'Jim Dobbs', value: 20, group: 'Friend' },
{ label: 'Katie Johnson', value: 3, group: 'Sister' },
{ label: 'Zena Wong', value: 2, group: 'Sister' }
];
Like this?
It's still missing a sort, but that can be easily remedied.
let beginning = {
Sister: {
1: { id: 1, name: 'Jesse Steven', active: false },
2: { id: 2, name: 'Zena Wong', active: true },
3: { id: 3, name: 'Katie Johnson', active: true },
},
Brother: {
10: { id: 10, name: 'Jeff Jacobs', active: true },
11: { id: 11, name: 'Mark Matha', active: false },
12: { id: 12, name: 'Kyle Ford', active: true },
},
Friend: {
20: { id: 20, name: 'Jim Dobbs', active: true },
}
};
let relations = Object.keys(beginning)
let final = relations.map(function(relation){
let num_keys = Object.keys(beginning[relation])
return num_keys.map(function(num_key){
beginning[relation][num_key]["group"] = relation
return beginning[relation][num_key]
})
})
.reduce(function(a, b){//flattens the returned array of arrays
return a.concat(b);
})
.filter(function(a){//filters out only active
return a["active"]
})
.map(function(a){//clean up some data
return {
label: a["name"],
value: a["id"],
group: a["group"]
}
})
console.log(final)
EDIT: Added sorting as the initial requirements asked for.
You can do this a number of ways, including for / in loops or some fancy stuff with ES2015, but a relatively simple functional example solution would be the following:
var activePeople = Object.keys(beginning).map(person => {
return Object.keys(beginning[person]).map(num => {
return (!!beginning[person][num].active) ? {
label: beginning[person][num].name,
value: beginning[person][num].id,
group: person
} : null
}).filter(i => !!i)
})
// flatten nested arrays
var final = [].concat.apply([], activePeople).sort((p1, p2) => {
if (p1.group < p2.group) {
return -1
} else if (p1.group > p2.group) {
return 1
}
if (p1.label < p2.label) {
return -1
}
return 1
})
I can propose faster one code:
"use strict";
let beginning = {
Sister: {
1: { id: 1, name: 'Jesse Steven', active: false },
2: { id: 2, name: 'Zena Wong', active: true },
3: { id: 3, name: 'Katie Johnson', active: true },
},
Brother: {
10: { id: 10, name: 'Jeff Jacobs', active: true },
11: { id: 11, name: 'Mark Matha', active: false },
12: { id: 12, name: 'Kyle Ford', active: true },
},
Friend: {
20: { id: 20, name: 'Jim Dobbs', active: true },
}
};
let groups = Object.keys(beginning).sort();
let final = [];
for (let i = 0, max = groups.length; i < max; i++) {
let keys = Object.keys(beginning[groups[i]]);
for (let j = 0, max2 = keys.length; j < max2; j++) {
let item = beginning[groups[i]][keys[j]];
if (item['active'] ) {
final.push({
label: item['name'],
value: keys[j],
group: groups[i]
});
}
}
}
console.log(final);

Reorder array of objects based on attribute

I have an array of objects, each with an 'id' and a 'name'. I'm retrieving an 'id' from the server and need to reorder the array starting from this id.
Example code:
var myList = [
{
id: 0,
name: 'Joe'
},
{
id: 1,
name: 'Sally'
},
{
id: 2,
name: 'Chris'
},
{
id: 3,
name: 'Tiffany'
},
{
id: 4,
name: 'Kerry'
}
];
Given an 'id' of 2, how can I reorder the array so my output is as follows:
var newList = [
{
id: 2,
name: 'Chris'
},
{
id: 3,
name: 'Tiffany'
},
{
id: 4,
name: 'Kerry'
},
{
id: 0,
name: 'Joe'
},
{
id: 1,
name: 'Sally'
}
];
Try this:
function orderList(list, id){
return list.slice(id).concat(list.slice(0,id));
}
Link to demo
You could slice the array at given index and return a new array using spread syntax.
const myList = [{id:0,name:'Joe'},{id:1,name:'Sally'},{id:2,name:'Chris'},{id:3,name:'Tiffany'},{id:4,name:'Kerry'}];
const slice = (arr, num) => [...arr.slice(num), ...arr.slice(0, num)];
console.log(slice(myList, 2));
myList.sort(function(a,b){
return a.id>2===b.id>2?a.id-b.id:b.id-a.id;
});
newList=myList;
http://jsbin.com/kenobunali/edit?console
You could splice the wanted part and use splice to insert it at the end of the array.
var myList = [{ id: 0, name: 'Joe' }, { id: 1, name: 'Sally' }, { id: 2, name: 'Chris' }, { id: 3, name: 'Tiffany' }, { id: 4, name: 'Kerry' }],
id = 2;
myList.splice(myList.length, 0, myList.splice(0, myList.findIndex(o => o.id === id)));
console.log(myList);
using es6 spread syntax
var myList = [{ id: 0, name: 'Joe' }, { id: 1, name: 'Sally' }, { id: 2, name: 'Chris' }, { id: 3, name: 'Tiffany' }, { id: 4, name: 'Kerry' }],
id = 2;
var index = myList.findIndex(o => o.id == id);
var arr = myList.splice(0, index);
var result = [...myList, ...arr];
console.log(result);

Manually change data items in datasource

I have the following datasource with data set to an array.
var dataArray = [
{ Id: 1, Name: "RootA", ParentId: null },
{ Id: 2, Name: "ChildA", ParentId: 1 },
{ Id: 3, Name: "RootB", ParentId: null },
{ Id: 4, Name: "ChildB", ParentId: 3 },
{ Id: 5, Name: "RootC", ParentId: null }
];
var treeListDataSource = new kendo.data.TreeListDataSource({
data: dataArray,
schema: {
model: {
id: "Id",
fields: {
parentId: { field: "ParentId", type: "number", nullable: true },
Id: { field: "Id", type: "number" }
}
}
}
});
This works.
Now I want to change the items in dataArray to:
var newData = [
{ Id: 6, Name: "RootD", ParentId: null },
{ Id: 7, Name: "ChildD", ParentId: 6 },
{ Id: 8, Name: "RootE", ParentId: null }
];
I tried:
Just setting it: dataArray = newData;
Setting via the data() method in the kendo datasource: treeListDataSource.data(newData)
But the grid doesn't display the new values. Instead is just says "no records".
Here's a demo.
I think there is some kind of bug that parentId field won't look up to modified field ParentId after initiation.
You can solve this with create the whole datasource definition again.
Your code should be like this:
<kendo-treelist id="treelist" k-options="treelistOptions"></kendo-treelist>
$scope.change = function() {
var treelist = $("#treelist").data().kendoTreeList;
var newData = [
{ Id: 6, Name: "RootD", ParentId: null },
{ Id: 7, Name: "ChildD", ParentId: 6 },
{ Id: 8, Name: "RootE", ParentId: null }
];
var newDs = new kendo.data.TreeListDataSource({
data: newData,
schema: {
model: {
id: "Id",
fields: {
parentId: { field: "ParentId", nullable: true },
Id: { field: "Id", type: "number" }
}
}
}
});
treelist.setDataSource(newDs);
};
I managed to get it working using the transport API. http://dojo.telerik.com/OBUSU/4
var treeListDataSource = new kendo.data.TreeListDataSource({
transport: {
read: function (options) {
var data = dataArray;
options.success(data);
}
},
...
});
function change() {
var newData = [
{ Id: 6, Name: "RootD", ParentId: null },
{ Id: 7, Name: "ChildD", ParentId: 6 },
{ Id: 8, Name: "RootE", ParentId: null }
];
dataArray = newData;
treeListDataSource.read();
};

Categories

Resources