-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathREADME.hbs
More file actions
205 lines (148 loc) · 8.32 KB
/
README.hbs
File metadata and controls
205 lines (148 loc) · 8.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# What's this?
This is a set of functions specialized in comparing and merging arrays of elements signed by unique set of IDs.
This is typically used in scenario in which client-side data-sets with changes coming from the an SQL server (server > client replication).
## How to install?
Simply open up a terminal, go to your project directory and run:
```
npm i --save array-merge-by-id
```
## Try it before you buy it
You can try out all the examples (listed below) in your browser at [RunKit](https://npm.runkit.com/array-merge-by-id).
# Functions by category
Comparing, merging, linking elements of two arrays:
* [`mergeA`](#mergeA) - merges new/changed elements into an existing array
* [`compareA`](#compareA) - compares elements of two arrays and returns an object containing common elements and differences
* [`linkA`](#linkA) - extends each child array element with a reference to it's parent element
* [`eachPair`](#eachPair) - calls a callback method for each matched elements of provided arrays
Searching & filtering:
* [`filterByKeys`](#filterByKeys) - extract all the array elements which match the given key values (or are indicated by a comparer function)
* [`findFirstById`](#findFirstById) - returns the first matched element of the given type
* [`indexOf`](#indexOf) - returns index of first matching element in the given array
* [`uniqueA`](#uniqueA) - copies unique elements from source to a new array, which is then returned
Modifying, sorting, adding, removing elements of a single array:
* [`concat`](#concat) - does an in-place concatination of elements of the source array at the end of target array
* [`clear`](#clear) - removes all the elements of the given array
* [`purgeA`](#purgeA) - removes elements indicated by a hit list from the provided array
* [`overwrite`](#overwrite) - removes all the elements of target and replaces them with elements from source
* [`sortOn`](#sortOn) - sorts the given array based on the given key name array (or comparer function)
Other helper functions:
* [`compileC`](#compileC) - compiles and returns a function which compares two data elements and detects which comes before which in an orderd list
* [`stringifyIDs`](#stringifyIDs) - creates CSV containing values of all the keys ending with "ID". It's usefull for debugging
## TypeScript typings
This lib was written in TypeScript, which is good news for people using TypeScript - all the typing information is included in the build (don't worry - it can still be used in vanilla JavaScript ... etc).
{{>main}}
# Param types
## CompareBy
Functions which compare array elements need to be instructed how two elements can be compared. This can be done in two ways:
* by passing an array of ID property names, which should be compared to determin the relation of the two objects
* by passing a comparer function, which receives tow elements and returns a numeric value indicating the relation of the objects
If an array of property names is passed, a comparer function will be compiled automatically (via `compileC`) function.
The following snippet shows how comparisson can be defined via a comparer function:
```javascript
let leftA = [
{cityID:1, cityName:'New York', weather:"windy"},
{cityID:2, cityName:'London', weather:"raining"}
];
let rightA = [
{cityID:2, cityName:'London', weather:"thunderstorm"},
{cityID:3, cityName:'Moscow', weather:"snowing"}
];
const comparerFn = (leftEl, rightEl) => {
if(leftEl.cityID===rightEl.cityID) {
return(0);
}
if(leftEl.cityID<rightEl.cityID) {
return(1);
}
return(0);
}
let diff = compareA(leftA, rightA, comparerFn);
```
The previous example can be re-written to define comparrison via property name array instead of comparer function:
```javascript
let leftA = [
{cityID:1, cityName:'New York', weather:"windy"},
{cityID:2, cityName:'London', weather:"raining"}
];
let rightA = [
{cityID:2, cityName:'London', weather:"thunderstorm"},
{cityID:3, cityName:'Moscow', weather:"snowing"}
];
let diff = compareA(leftA, rightA, ["cityID"]);
```
### Descending order
If a ID name array is passed as `key_columns` params, the compiled function will compare elements in ascending order.
We can change this behaviour by appending `:desc` to a ID name ... like so: ['cityID:desc','streetID:desc']
See an example given for the [`sortOn` function](#sortonsource-key_columns).
## ArrayDiffConfig
We can modify the way the functions work, by providing an **config object**. All the options in the `config` object are optional.
Here's a list of available options:
* [`sortLeftBy`](#sortleftby-and-sortrightby) - how should the `leftA` array be sorted
* [`sortRightBy`](#sortleftby-and-sortrightby) - how should the `rightA` be sorted
* `skipSort` - set it to `true` if arrays are not to be sorted
* `unique` - set it to `true` if are all the array elements unique - it speeds up the algorithm
* `linkName` - property assigned to the `rightA` elements, which should be pointing to the matching element in the `leftA`
* `mapName` - property assigned to the `leftA` elements, containig array of all the matched elemens from the `rightA`
* `callbackFn` - a callback function, which should be called for each of the matched element pairs
### `sortLeftBy` and `sortRightBy`
**Description:** defines how the arrays passed to the function should be sorted
**Defaults to**: value passed as `key_columns` param
**Expected value**: we can pass a function or an array of ID param names (see [CompareBy](#compareby))
In order to be more efficient, functions which rely on comparing array elements will sort both of the given arrays.
By default the functions use `key_columns` parameter to sort the arrays.
This can be overriden by specifying a dedicated sorting order for each of the two arrays:
* `config.sortLeftBy` = defines how the left array should be sorted (passed as the first param)
* `config.sortRightBy` = defines how the right array should be sorted (passed as the second param)
Sorting of an array can be disabled by assigning `null` to corresponding sort config param:
```javascript
{
sortLeftBy: null // don't sort the left array
}
```
## ArrayPurgeConfig
This config si very similar to `ArrayDiffConfig` param type. The following params are the same as in [`ArrayDiffConfig`](#arraydiffconfig):
* `sortLeftBy`
* `sortRightBy`
* `skipSort`
The following params are unique to this param type:
* `sortBy` = how should both arrays be sorted
* `mapRemoved` - flag indicating should removed elements be mapped and returned
* `matchMulti` - can an element from the hit list array be matched with multiple elements from the target array (defaults to `false`)
## ArrayUniqueConfig
* `skipSort` - set it to `true` if arrays are not to be sorted
* `elFreq` - output param - an array in which element frequency is to be recorded (see the example given in the [`uniqueA` method description](#uniqueA))
# Return Types
## `ArrayDiffResult`
``ArrayDiffResult`` contains results of comparing two arrays. It has the following structure:
```javascript
{
// an array of elements from left array (`leftA` param), which have not
// been matched with any of the elements of the right array (`rightA` param)
leftDiff:Array,
// an array of elements from left array (`leftA` param),
// which have been matched with at leas one element of the right array (`rightA` param)
leftCommon:Array,
// an array of elements from right array (`rightA` param), which have not
// been matched with any of the elements of the left array (`leftA` param)
rightCommon:Array,
// an array of elements from right array (`rightA` param),
// which have been matched with at leas one element of the left array (`leftA` param)
rightDiff:Array
}
```
## `ArrayLinkResult`
``ArrayLinkResult`` contains results of linking two arrays. It has the following structure:
```javascript
{
// parent elements with no matched child elements
childless:Array,
// parent elements with matching children
parents:Array,
// child elements with matching parent
children:Array,
// child elements without a matching parent
orphans:Array
}
```
# License
MIT License, [http://www.opensource.org/licenses/MIT](http://www.opensource.org/licenses/MIT)