{"id":26975169,"url":"https://github.com/izure1/node-relation","last_synced_at":"2025-04-03T11:19:22.316Z","repository":{"id":44344207,"uuid":"293137649","full_name":"izure1/node-relation","owner":"izure1","description":"This module helps you manage string, numbers as a group.","archived":false,"fork":false,"pushed_at":"2024-04-25T19:47:37.000Z","size":206,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-25T20:49:15.647Z","etag":null,"topics":["backend","data-structures","front-end","javascript","linked-list","linkedlist","math","relationship","tree","tree-structure"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/izure1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-05T19:02:40.000Z","updated_at":"2024-04-25T19:47:40.000Z","dependencies_parsed_at":"2022-09-16T08:52:44.238Z","dependency_job_id":null,"html_url":"https://github.com/izure1/node-relation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izure1%2Fnode-relation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izure1%2Fnode-relation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izure1%2Fnode-relation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izure1%2Fnode-relation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/izure1","download_url":"https://codeload.github.com/izure1/node-relation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246989732,"owners_count":20865331,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","data-structures","front-end","javascript","linked-list","linkedlist","math","relationship","tree","tree-structure"],"created_at":"2025-04-03T11:19:21.721Z","updated_at":"2025-04-03T11:19:22.292Z","avatar_url":"https://github.com/izure1.png","language":"TypeScript","readme":"# node-relation\r\n\r\n[![jsdelivr](https://data.jsdelivr.com/v1/package/npm/node-relation/badge)](https://www.jsdelivr.com/package/npm/node-relation)\r\n![Github node.js workflow](https://github.com/izure1/node-relation/actions/workflows/node.js.yml/badge.svg)\r\n\r\nThis module helps you manage string, numbers, object as a group.\r\nCheck the code.\r\n\r\n```javascript\r\nimport { Relationship } from 'node-relation'\r\n\r\nlet state = new Relationship().to('a', 'b')\r\nstate.nodes // ['a', 'b']\r\n\r\nstate = state.to('b', 'c')\r\nstate.nodes // ['a', 'b', 'c']\r\n\r\nstate = state.to('c', 'd')\r\nstate.from('c').nodes // ['c', 'd']\r\n\r\nstate = state.to('d', 'a')\r\nstate.from('c').nodes // ['a', 'b', 'c', 'd']\r\n```\r\n\r\n## Install\r\n\r\nYou can download in npm [node-relation](https://www.npmjs.com/package/node-relation).\r\n\r\n```bash\r\nnpm install node-relation\r\n```\r\n\r\n## How to use\r\n\r\n### Browser (esnext)\r\n\r\n```javascript\r\nimport { Relationship } from 'https://cdn.jsdelivr.net/npm/node-relation@5.x.x/+esm'\r\n```\r\n\r\n### Node.js\r\n\r\n```javascript\r\nimport { Relationship } from 'node-relation'\r\n\r\nconst state = new Relationship().to('a', 'b', 'c')\r\n```\r\n\r\n## Methods\r\n\r\nThe data inside the instance is immutable.\r\nThe method does not modify the data inside, it returns the result of the calculation as a new instance.\r\n\r\n### ***to***(source: `T`, ...targets: `T[]`): `Relationship`\r\n\r\nCreates a new refer between nodes, and returns it as a Relationship instance.\r\nThis is one-sided relationship between both nodes.\r\n\r\n```javascript\r\nconst state = new Relationship().to('language', 'English', 'Korean', 'Japanese')\r\n```\r\n\r\n```bash\r\n# state\r\nlanguage ─\u003e English\r\nlanguage ─\u003e Korean\r\nlanguage ─\u003e Japanese\r\n```\r\n\r\n### ***both***(a: `T`, ...b: `T[]`): `Relationship`\r\n\r\nCreates a new relationship between nodes, and returns it as a new Relationship instance.\r\nBoth nodes will know each other.\r\n\r\n```javascript\r\nconst A = new Relationship().to('language', 'English', 'Korean', 'Japanese')\r\nconst B = A.both('English', 'US', 'France', 'Italy')\r\n```\r\n\r\n```bash\r\n# A\r\nlanguage ─\u003e English\r\nlanguage ─\u003e Korean\r\nlanguage ─\u003e Japanese\r\n\r\n# B\r\nlanguage ─\u003e English\r\nEnglish \u003c─\u003e US\r\nEnglish \u003c─\u003e France\r\nEnglish \u003c─\u003e Italy\r\nlanguage ─\u003e Korean\r\nlanguage ─\u003e Japanese\r\n```\r\n\r\n### ***all***(...nodes: `T[]`): `Relationship`\r\n\r\nCreates a new relationship between all each other nodes, and returns it as a new Relationship instance.\r\nAll nodes will know each others.\r\n\r\n```javascript\r\nconst state = new Relationship().all('john', 'harris', 'richard')\r\n```\r\n\r\n```bash\r\njohn \u003c─\u003e harris\r\nharris \u003c─\u003e richard\r\nrichard \u003c─\u003e john\r\n```\r\n\r\n### ***from***(source: `T`, depth?: `number` = -1): `Relationship`\r\n\r\nOnly the nodes that are related to the node received by the parameter are filtered and returned in a new Relationship instance.\r\nYou can control calculation depth relationship with depth parameter. If depth parameter are negative, it's will be calculate all relationship between nodes in instance. Depth parameter default value is -1.\r\n\r\n```javascript\r\nlet state = new Relationship()\r\n  .to('language', 'English', 'Korean', 'Japanese')\r\n  .both('English', 'US', 'France', 'Italy')\r\n\r\nstate.from('language').nodes // language, English, Korean, Japanese, US, France, Italy\r\nstate.from('English').nodes // English, US, France, Italy\r\n```\r\n\r\n### ***where***(filter: (node: `T`, i: `number`, array: `T[]`) =\u003e `boolean`, depth?: `number` = -1): `Relationship`\r\n\r\nReturns a new relationship instance with only nodes that meet the conditions.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .both('English', 'US', 'France', 'Italy')\r\n\r\nstate.where((v) =\u003e v === 'English').nodes // English, US, France, Italy\r\n```\r\n\r\n### ***without***(...nodes: `T[]`): `T[]`\r\n\r\nReturns the remaining nodes except those received as parameters from the current relationship instance.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('language', 'English', 'Korean', 'Japanese')\r\n\r\nstate.from('language').nodes // language, English, Korean, Japanese\r\nstate.from('language').without('language') // English, Korean, Japanese\r\n```\r\n\r\n### ***unlinkTo***(source: `T`, ...targets: `T[]`): `Relationship`\r\n\r\nDeletes the relationship between nodes and returns it as a new Relationship instance.\r\nThis is one-sided cut off between both nodes.\r\n\r\n```javascript\r\nlet state = new Relationship()\r\n  .to('a', 'b', 'c')\r\n\r\nstate = state.unlinkTo('a', 'b')\r\nstate.nodes // a, c\r\n```\r\n\r\n### ***unlinkBoth***(a: `T`, ...b: `T[]`): `Relationship`\r\n\r\nDeletes the relationship between nodes and returns it as a new Relationship instance.\r\nBoth nodes will cut off each other.\r\n\r\n```javascript\r\nlet state = new Relationship()\r\n  .both('a', 'b', 'c')\r\n\r\nstate = state.unlinkBoth('a', 'b')\r\nstate.nodes // a, c\r\n```\r\n\r\n### ***drop***(...nodes: `T[]`): `Relationship`\r\n\r\nDelete the node. If the node associated with the deleted node is isolated, it is deleted together. Returns the result with a new Relationship instance.\r\n\r\n```javascript\r\nlet state = new Relationship()\r\n  .to('a', 'b', 'c')\r\n\r\nstate = state.drop('a')\r\nstate.nodes // empty\r\n\r\nlet stateB = new Relationship()\r\n  .to('a', 'b')\r\n  .to('b', 'c')\r\n\r\nstateB = stateB.drop('b')\r\nstateB.nodes // empty\r\n\r\nlet stateC = new Relationship()\r\n  .to('a', 'b')\r\n  .to('b', 'c')\r\n  .to('c', 'a')\r\n\r\nstateC = stateC.drop('b')\r\nstateC.nodes // a, c\r\n```\r\n\r\n### ***has***(node: `T`): `boolean`\r\n\r\nReturns whether the instance contains that node.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'b', 'c')\r\n\r\nconst exists = state.has('a') // true\r\n```\r\n\r\n### ***hasAll***(...nodes: `T[]`): `boolean`\r\n\r\nReturns whether the instance contains all of its nodes.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'b', 'c')\r\n\r\nconst existsAll = state.hasAll('a', 'b') // true\r\n```\r\n\r\n### ***weight***(node: `T`, log?: `boolean` = `false`): `number`\r\n\r\nReturns how many nodes are related to the node received by the parameter.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'd')\r\n  .to('b', 'd')\r\n  .to('c', 'd')\r\n\r\nconst weight = state.weight('d') // 3\r\n```\r\n\r\n### ***weights***(log?: `boolean` = `false`, normalize?: `boolean` = `false`, toScale?: `boolean` = `false`): `Map\u003cT, number\u003e`\r\n\r\nReturns the weight of all nodes. Check the `weight` method.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'd')\r\n  .to('b', 'd')\r\n  .to('c', 'd')\r\n  .to('d', 'a')\r\n\r\n// Map\u003c[['a', 4], ['b', 0], ['c', 0], ['d', 4]]\u003e\r\nconst weights = state.weights()\r\n\r\n// Map\u003c[['a', 1], ['b', 0], ['c', 0], ['d', 1]]\u003e\r\nconst normalizedWeights = state.weights(false, true)\r\n```\r\n\r\n### ***entry***(node: `T`, log?: `boolean` = `false`): `number`\r\n\r\nReturns how many nodes are related to the node received by the parameter.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'b')\r\n  .to('a', 'c')\r\n  .to('a', 'd')\r\n\r\nconst entry = state.entry('a') // 3\r\n```\r\n\r\n### ***entries***(log?: `boolean` = `false`, normalize?: `boolean` = `false`, toScale?: `boolean` = `false`): `Map\u003cT, number\u003e`\r\n\r\nReturns the entry value of all nodes. Check the `entry` method.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'b')\r\n  .to('a', 'c')\r\n  .to('a', 'd')\r\n  .to('b', 'a')\r\n\r\n// Map\u003c[['a', 4], ['b', 4], ['c', 0], ['d', 0]]\u003e\r\nconst entries = state.entries()\r\n\r\n// Map\u003c[['a', 1], ['b', 1], ['c', 0], ['d', 0]]\u003e\r\nconst normalizedEntries = state.entries(false, true)\r\n```\r\n\r\n### ***depth***(source: `T`, target: `T`, log?: `boolean` = `false`): `number`\r\n\r\nReturns the found minimum depth to between source to target.\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'b')\r\n  \r\nstate.depth('a', 'b') // 1\r\nstate.depth('b', 'a') // Infinity\r\n```\r\n\r\n### ***distance***(a: `T`, b: `T`, log?: `boolean` = `false`): `number`\r\n\r\nReturns the found minimum distance to between both nodes. This is same as `Math.min(this.depth(a, b), this.depth(b, a))`\r\n\r\n```javascript\r\nconst state = new Relationship()\r\n  .to('a', 'b')\r\n  .to('b', 'c')\r\n\r\nstate.distance('b', 'a') // 1\r\nstate.distance('a', 'c') // 2\r\n```\r\n\r\n### ***merge***(...datasets: `RelationData[]`): `Relationship`\r\n\r\nMerge a relation dataset with this instance, and returns it as a new Relationship instance.\r\nIf there is a non-overlapping dataset, It will be append to instance.\r\n\r\n```javascript\r\nconst A = state.to('user-a', 'user-b')\r\nconst B = state.to('user-c', 'user-d')\r\nconst C = A.merge(B.dataset)\r\n\r\nC.nodes // user-a, user-b, user-c, user-d\r\n```\r\n\r\n### ***raw***(node: `T`): `T`|`undefined`\r\n\r\nThis method for instance that `useEqual` options. It returns a original value from `node` parameter.\r\nIt will be useful when using between returned Map from `nodeset`, `oneHot`, `label` getters and `weights` method.\r\n\r\n```javascript\r\nconst useEqual = true\r\nconst state = new Relationship(undefined, useEqual).to({ name: 'a' }, { name: 'b' })\r\nconst weights = state.weights()\r\n\r\nweights.get({ name: 'b' })\r\n// undefined. because 'weights' map instance doesn't using equal system.\r\n\r\nconst raw = state.raw({ name: 'b' })\r\nweights.get(raw) // 1\r\n```\r\n\r\n### ***clear***(): `void`\r\n\r\nDestroy the data in the instance. It is used for garbage collector.\r\n\r\n### ***constructor***(dataset?: `RelationData[]`, useEqual?: `boolean` = `false`): `Relationship`\r\n\r\nYou can pass dataset parameter to init this instance.\r\nThe `RelationData` is type of 2-dimensional tuple array. Check dataset getter description.\r\n\r\n```javascript\r\nconst state = new Relationship([ ['a', ['b', 'c', 'd']] ])\r\nconst clone = new Relationship(state.dataset) \r\n```\r\n\r\nIf you want ignore strict references to variables, You can use the `useEqual` option. This helps you treat other objects as the same variable.\r\n\r\n```javascript\r\nconst useEqual = true\r\nlet state = new Relationship(null, useEqual)\r\n\r\nstate = state.to({ a: 1 }, { a: 2 })\r\nstate = state.to({ a: 1 }, { a: 3 })\r\nstate.nodes // { a: 1 }, { a: 2 }, { a: 3 }\r\n```\r\n\r\n### `(getter)` ***dataset***: `RelationData[]`\r\n\r\nReturns as 2-dimensional array of relationships between nodes in the instance. Relationships are returned to saveable data-type(json).\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c', 'd')\r\nstate.dataset // [ ['a', ['b']], ['b', ['c', 'd']] ]\r\n```\r\n\r\n### `(getter)` ***nodes***: `T[]`\r\n\r\nGet all nodes from the instance.\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c')\r\nstate.nodes // a, b, c\r\n```\r\n\r\n### `(getter)` ***children***: `T[]`\r\n\r\nGet all children nodes without primary from the instance.\r\n\r\n```javascript\r\nconst a = new Relationship().to('a', 'b').to('b', 'c')\r\na.from('a').children // b, c\r\n\r\nconst b = a.both('d', 'e')\r\nb.from('d').children // d, e\r\n```\r\n\r\n### `(getter)` ***nodeset***: `Set\u003cT\u003e`\r\n\r\nGet all nodes as Set object from the instance.\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c')\r\nstate.nodeset // Set\u003c['a', 'b', 'c']\u003e\r\n```\r\n\r\n### `(getter)` ***oneHot***: `Map\u003cT, number[]\u003e`\r\n\r\nGet all nodes as one-hot vectors from the instance. It could be used as dataset for machine learning.\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c')\r\nconst vectors = state.oneHot\r\n\r\nvectors // Map\u003c[['a', [1, 0, 0]], ['b', [0, 1, 0]], ['c', [0, 0, 1]]]\u003e\r\nArray.from(vectors.values()) // [[1, 0, 0], [0, 1, 0], [0, 0, 1]]\r\n```\r\n\r\n### `(getter)` ***zeroVector***: `number[]`\r\n\r\nGet a 1-dimensional vector that was filled 0. The vector's size are same as nodes length of instance. This is useful for representing data that does not belong to anything. It could be used as dataset for machine learning.\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c')\r\n\r\nconst vectors = state.oneHot\r\nconst zeroVector = state.zeroVector // [0, 0, 0]\r\nconst allVectors = [zeroVector, ...vectors.values()]\r\n```\r\n\r\n### `(getter)` ***label***: `Map\u003cT, number\u003e`\r\n\r\nGet all nodes as labeled vector from the instance. It could be used as dataset for machine learning.\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c')\r\nconst vector = state.label\r\n\r\nvector // Map\u003c[['a', 1], ['b', 2], ['c', 3]]\u003e\r\nArray.from(vector.values()) // [1, 2, 3]\r\n```\r\n\r\n### `(getter)` ***clusters***: `T[][]`\r\n\r\nReturns the clustering models of this instance in the form of a two-dimensional array.\r\n\r\n```javascript\r\nlet state = new Relationship().to('a', 'b', 'c').to('d', 'e')\r\nstate.clusters // [[a, b, c], [d, e]]\r\n\r\nstate = state.to('e', 'a')\r\nstate.clusters // [[a, b, c, d, e]]\r\n```\r\n\r\n### `(getter)` ***reverse***: `Relationship`\r\n\r\nReturns the instance in which the relationship of the node is reversed.\r\n\r\n```javascript\r\nconst state = new Relationship().to('a', 'b').to('b', 'c')\r\n\r\nstate.reverse.from('c').nodes // [a, b, c]\r\n```\r\n\r\n## Try it simply\r\n\r\n## Applying (Advanced usage, with Typescript)\r\n\r\n```javascript\r\n// The data structure what you want\r\n// {\r\n//   'server-a': [userA, userB],\r\n//   'server-b': [userC]\r\n// }\r\n\r\nimport { Relationship } from 'node-relation'\r\n\r\ntype ServerName = 'server-a' | 'server-b'\r\nclass User {\r\n  ...\r\n}\r\n\r\nconst userA = new User\r\nconst userB = new User\r\nconst userC = new User\r\n\r\nlet state: Relationship\u003cServerName|User\u003e = new Relationship\r\n\r\nstate = state.to('server-a', userA, userB)\r\nstate = state.to('server-b', userC)\r\n\r\nconsole.log( state.from('server-b').without('server-b') ) // userC\r\n```\r\n\r\n```javascript\r\nimport { RawRelationship } from 'node-relation'\r\n\r\nconst sentence = 'what will the fat cat sit on'\r\nconst words = sentence.split(' ')\r\n\r\nconst state = new RawRelationship\u003cstring\u003e()\r\n\r\nwords.forEach((word, i) =\u003e {\r\n  const next = words[i+1]\r\n  if (next) {\r\n    state.to(word, next)\r\n  }\r\n})\r\n\r\nconst oneHot = state.oneHot // Map\u003c[['what', [1,0,0,0,0,0,0]], ['will', [0,1,0,0,0,0,0]], ...]\u003e\r\nconst oneHotVectors = Array.from(oneHot.values())\r\n\r\nconst label = state.label // Map\u003c[['what', 1], ['will', 2], ...]\u003e\r\nconst labels = Array.from(label.values())\r\n```\r\n\r\n### Migration 3.x.x to 4.x.x\r\n\r\nCheck [readme](https://github.com/izure1/node-relation/blob/master/Migration_3_to_4.md)\r\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fizure1%2Fnode-relation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fizure1%2Fnode-relation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fizure1%2Fnode-relation/lists"}