Skip to content

Split list #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions bin/performance.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use strict"
const LTT = require('../dist/old/list-to-tree.npm.js');
const LTT1 = require('../dist/list-to-tree.js');
const IronTree = require('@denq/iron-tree');

const LENGTH = 20000;
const LENGTH = 25000;

function getList() {

@@ -29,8 +30,12 @@ function performanceCalc(fn, ...params) {
console.log(`Result: ${result}. Execution Time: ${end - start} ms`)
}

const list = getList();
const xlist = list.map(item => Object.assign({}, item));

function runListToTree() {
var ltt = new LTT(getList(), {
// const _list = Array(list.length).fill().map((item, index) => list[index]);
var ltt = new LTT(xlist, {
key_id: 'id',
key_parent: 'parent',
key_child: 'children',
@@ -41,7 +46,7 @@ function runListToTree() {

function runIronTree() {
const tree = new IronTree({ id: 0 });
getList().forEach((item, index) => {
list.forEach((item, index) => {
tree.add((parentNode) => {
return parentNode.get('id') === item.parent;
}, item);
@@ -53,10 +58,11 @@ function runIronTree() {
}

function runNewListToTree() {
const ltt = new LTT1(getList(), {
const ltt = new LTT1(list, {
key_id: 'id',
key_parent: 'parent',
key_child: 'children',
many_items: true,
});
var tree = ltt.GetTree();
return 'new list-to-tree';
99 changes: 72 additions & 27 deletions dist/list-to-tree.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
const IronTree = require('@denq/iron-tree');
const sortBy = require('../utils/sort-by');
const compareById = require('../utils/compare-by-id');

const defaultOptions = {
key_id: 'id' ,
key_parent: 'parent' ,
key_child: 'child',
empty_children: false,
};

function sortBy(collection, propertyA, propertyB) {
return collection.sort(function(a, b) {
if (a[propertyB] < b[propertyB]) {
if (a[propertyA] > b[propertyA]) {
return 1;
}
return -1;
} else {
if (a[propertyA] < b[propertyA]) {
return -1;
}
return 1;
}
});
many_items: false,
};

module.exports = class LTT{
@@ -30,29 +17,87 @@ module.exports = class LTT{

options = Object.assign({}, defaultOptions, options);
this.options = options;
const { key_id, key_parent } = options;

sortBy(_list, key_parent, key_id);
if (options.many_items) {
const collections = this.split(_list);
this.tree = collections.map((item) => {
return this.buildTreeFromList(item);
});
} else {
this.tree = this.buildTreeFromList(_list);
}
}

buildTreeFromList(list) {
const { key_id, key_parent } = this.options;

sortBy(list, key_parent, key_id);
const tree = new IronTree({ [key_id]: 0 });
_list.forEach((item, index) => {
list.forEach((item, index) => {
tree.add((parentNode) => {
return parentNode.get(key_id) === item[key_parent];
}, item);
});

this.tree = tree;
return tree;
}

sort(criteria) {
this.tree.sort(criteria);
const { many_items } = this.options;
if (many_items) {
this.tree.forEach((item) => {
item.sort(criteria);
});
//hack
this.tree = this.tree.map((item) => {
const id = item.rootNode.children[0].get('id')
item.set('id', id);
item.set('xid', id);
return item;
});
this.tree.sort(criteria);
// end hack
} else {
this.tree.sort(criteria);
}
}

split(list) {
const { key_id, key_parent } = this.options;

list.sort(compareById(true, key_parent));
const rootParentId = list[0][key_parent];

const collection = [];
list.forEach((item) => {
if (item[key_parent] === rootParentId) {
collection.push([item]);
} else {
collection.forEach((el) => {
el.forEach((child) => {
if (child[key_id] === item[key_parent]) {
el.push(item);
}
});
});

}
});
return collection;
}

GetTree() {
const { key_child, empty_children } = this.options;
return this.tree.toJson({
key_children: key_child,
empty_children: false,
})[key_child];
const { key_child, empty_children, many_items } = this.options;
if (many_items) {
const trees = this.tree.map((item) => {
return item.toJson(this.options).children[0];
});
return [].concat(...trees);
} else {
return this.tree.toJson({
key_children: key_child,
empty_children: false,
})[key_child];
}
}

}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -34,6 +34,6 @@
"jasmine": "^2.8.0"
},
"dependencies": {
"@denq/iron-tree": "^1.2.0"
"@denq/iron-tree": "^1.3.0"
}
}
88 changes: 88 additions & 0 deletions spec/split-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require("util").inspect.defaultOptions.depth = null;
const LTT = require('../dist/list-to-tree');

function compareById(vector) {
return (a, b) => {
const aid = Number(a.get('id'));
const bid = Number(b.get('id'));
if (aid > bid) {
return vector ? 1 : -1;
} else if (aid < bid) {
return vector ? -1 : 1;
} else {
return 0
}
};
}

const key_id = 'id';
const key_parent = 'parent';
const key_child = 'child';
const many_items = true;

const list = [
{ id: 1, parent: 0 },
{ id: 2, parent: 0 },
{ id: 3, parent: 2 },
{ id: 4, parent: 3 },
{ id: 5, parent: 2 },
{ id: 6, parent: 1 },
{ id: 7, parent: 0 },
{ id: 8, parent: 7 },
{ id: 9, parent: 7 },
{ id: 10, parent: 8 },
{ id: 11, parent: 6 },
{ id: 12, parent: 0 },
];
const ltt = new LTT(list, {
key_id,
key_parent,
key_child,
many_items,
});
ltt.sort(compareById(true));

describe('Split', function() {

it('Run method - split', function() {
const collection = ltt.split(list);
expect(collection.length).toBe(4);

expect(collection[0][0].id).toBe(7);
expect(collection[0][1].id).toBe(8);
expect(collection[0][2].id).toBe(9);
expect(collection[0][3].id).toBe(10);

expect(collection[1][0].id).toBe(1);
expect(collection[1][1].id).toBe(6);
expect(collection[1][2].id).toBe(11);

expect(collection[2][0].id).toBe(2);
expect(collection[2][1].id).toBe(5);
expect(collection[2][2].id).toBe(3);
expect(collection[2][3].id).toBe(4);

expect(collection[3][0].id).toBe(12);
});

it('GetTree', function() {
const tree = ltt.GetTree();

expect(tree[0].id).toBe(1);
expect(tree[0].children[0].id).toBe(6);
expect(tree[0].children[0].children[0].id).toBe(11);

expect(tree[1].id).toBe(2);
expect(tree[1].children[0].id).toBe(3);
expect(tree[1].children[0].children[0].id).toBe(4);
expect(tree[1].children[1].id).toBe(5);

expect(tree[2].id).toBe(7);
expect(tree[2].children[0].id).toBe(8);
expect(tree[2].children[0].children[0].id).toBe(10);
expect(tree[2].children[1].id).toBe(9);

expect(tree[3].id).toBe(12);
});

})
13 changes: 13 additions & 0 deletions utils/compare-by-id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = function compareById(vector, key) {
return (a, b) => {
const aid = Number(a[key]);
const bid = Number(b[key]);
if (aid > bid) {
return vector ? 1 : -1;
} else if (aid < bid) {
return vector ? -1 : 1;
} else {
return 0
}
};
}
15 changes: 15 additions & 0 deletions utils/sort-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = function sortBy(collection, propertyA, propertyB) {
return collection.sort(function(a, b) {
if (a[propertyB] < b[propertyB]) {
if (a[propertyA] > b[propertyA]) {
return 1;
}
return -1;
} else {
if (a[propertyA] < b[propertyA]) {
return -1;
}
return 1;
}
});
}