Skip to content

Commit 65e19ef

Browse files
committed
merge.deep
1 parent 5f4a1bf commit 65e19ef

17 files changed

Lines changed: 463 additions & 57 deletions

.vscode/launch.json

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@
22
"version": "0.2.0",
33
"configurations": [
44
{
5-
"type": "node",
6-
"request": "launch",
7-
"name": "Test File(current)",
8-
"program": "${workspaceRoot}/node_modules/jest/bin/jest.js",
9-
"args": [
10-
"--verbose",
11-
"-i",
12-
"-u",
13-
"--no-cache",
14-
"${fileBasenameNoExtension}"
15-
],
16-
"console": "integratedTerminal",
17-
"internalConsoleOptions": "neverOpen"
18-
}
5+
"type": "node",
6+
"request": "launch",
7+
"name": "Debug Test(spec or source)",
8+
"autoAttachChildProcesses": true,
9+
"skipFiles": [
10+
"<node_internals>/**",
11+
"**/node_modules/**"
12+
],
13+
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
14+
"args": [
15+
"run",
16+
"${fileDirnameBasename}/${fileBasenameNoExtension}"
17+
],
18+
"smartStep": true,
19+
"console": "integratedTerminal"
20+
}
1921
]
2022
}

README.md

Lines changed: 124 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7484,17 +7484,17 @@ it('R.maxBy', () => {
74847484
74857485
```typescript
74867486

7487-
merge<Source>(source: Source): <T>(data: T) => Merge<T, Source>
7487+
merge<Source>(source: Source): <T>(newProps: T) => Merge<T, Source>
74887488
```
74897489
7490-
It creates a copy of `target` object with overwritten `newProps` properties.
7490+
It creates a copy of `source` object with overwritten `newProps` properties.
74917491
74927492
<details>
74937493
74947494
<summary>All TypeScript definitions</summary>
74957495
74967496
```typescript
7497-
merge<Source>(source: Source): <T>(data: T) => Merge<T, Source>;
7497+
merge<Source>(source: Source): <T>(newProps: T) => Merge<T, Source>;
74987498
```
74997499
75007500
</details>
@@ -7552,6 +7552,99 @@ it('R.merge', () => {
75527552
75537553
[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#merge)
75547554
7555+
### mergeDeep
7556+
7557+
```typescript
7558+
7559+
mergeDeep<Source>(source: Source): <T>(newProps: T) => Merge<T, Source>
7560+
```
7561+
7562+
<details>
7563+
7564+
<summary>All TypeScript definitions</summary>
7565+
7566+
```typescript
7567+
mergeDeep<Source>(source: Source): <T>(newProps: T) => Merge<T, Source>;
7568+
```
7569+
7570+
</details>
7571+
7572+
<details>
7573+
7574+
<summary><strong>R.mergeDeep</strong> source</summary>
7575+
7576+
```javascript
7577+
import { type } from './type.js'
7578+
import { isArray } from './_internals/isArray.js'
7579+
7580+
const isObject = (x) => type(x) === 'Object'
7581+
7582+
function mergeDeepFn(source, objectWithNewProps) {
7583+
return [source, objectWithNewProps].reduce((prev, obj) => {
7584+
Object.keys(obj).forEach((key) => {
7585+
const pVal = prev[key]
7586+
const oVal = obj[key]
7587+
7588+
if (isArray(pVal) && isArray(oVal)) {
7589+
prev[key] = oVal
7590+
} else if (isObject(pVal) && isObject(oVal)) {
7591+
prev[key] = mergeDeepFn(pVal, oVal)
7592+
} else {
7593+
prev[key] = oVal
7594+
}
7595+
})
7596+
7597+
return prev
7598+
}, {})
7599+
}
7600+
7601+
export function mergeDeep(source) {
7602+
return (objectWithNewProps) => mergeDeepFn(source, objectWithNewProps)
7603+
}
7604+
```
7605+
7606+
</details>
7607+
7608+
<details>
7609+
7610+
<summary><strong>Tests</strong></summary>
7611+
7612+
```javascript
7613+
import { mergeDeep } from './mergeDeep.js'
7614+
7615+
test('happy', () => {
7616+
const source = {
7617+
a: 1,
7618+
b: [1, 2],
7619+
c: {
7620+
d: 1,
7621+
f: 2,
7622+
e: [1, 2],
7623+
h: [1, 2],
7624+
},
7625+
}
7626+
const objectWithNewProps = {
7627+
b: [3],
7628+
c: {
7629+
f: 3,
7630+
s: 3,
7631+
e: [3],
7632+
},
7633+
q: 3,
7634+
}
7635+
expect(mergeDeep(source)(objectWithNewProps)).toEqual({
7636+
a: 1,
7637+
b: [3],
7638+
c: { d: 1, f: 3, e: [3], h: [1, 2], s: 3 },
7639+
q: 3,
7640+
})
7641+
})
7642+
```
7643+
7644+
</details>
7645+
7646+
[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeDeep)
7647+
75557648
### mergeTypes
75567649
75577650
```typescript
@@ -10403,7 +10496,8 @@ range(startInclusive: number, endInclusive: number) : number[];
1040310496
export function range(a, b) {
1040410497
const start = b === undefined ? 0 : a
1040510498
const end = b === undefined ? a : b
10406-
if (end<= start) {
10499+
if (end === start) return [start]
10500+
if (end < start) {
1040710501
return []
1040810502
}
1040910503
const len = end - start
@@ -10422,9 +10516,12 @@ import { range } from './range.js'
1042210516

1042310517
test('happy', () => {
1042410518
expect(range(5)).toEqual([0, 1, 2, 3, 4, 5])
10425-
expect(range(3,5)).toEqual([3, 4, 5])
10426-
expect(range(5,3)).toEqual([])
10427-
expect(range(0)).toEqual([])
10519+
expect(range(3, 5)).toEqual([3, 4, 5])
10520+
expect(range(5, 3)).toEqual([])
10521+
expect(range(5, 5)).toEqual([5])
10522+
expect(range(0)).toEqual([0])
10523+
expect(range(1)).toEqual([0, 1])
10524+
expect(range(2)).toEqual([0, 1, 2])
1042810525
})
1042910526
```
1043010527
@@ -10477,7 +10574,8 @@ rangeDescending(endInclusive: number) : number[];
1047710574
```javascript
1047810575
export function rangeDescending(start, b) {
1047910576
const end = b === undefined ? 0 : b
10480-
if (start <= end) {
10577+
if (start === end) return [start]
10578+
if (start < end) {
1048110579
return []
1048210580
}
1048310581
const len = start - end
@@ -10496,9 +10594,12 @@ import { rangeDescending } from './rangeDescending.js'
1049610594

1049710595
test('happy', () => {
1049810596
expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0])
10499-
expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3])
10500-
expect(rangeDescending(5, 7)).toEqual([])
10501-
expect(rangeDescending(5, 5)).toEqual([])
10597+
expect(rangeDescending(7, 3)).toEqual([7, 6, 5, 4, 3])
10598+
expect(rangeDescending(0)).toEqual([0])
10599+
expect(rangeDescending(1)).toEqual([1, 0])
10600+
expect(rangeDescending(2)).toEqual([2, 1, 0])
10601+
expect(rangeDescending(5, 7)).toEqual([])
10602+
expect(rangeDescending(5, 5)).toEqual([5])
1050210603
})
1050310604
```
1050410605
@@ -12054,7 +12155,7 @@ splitEvery<T>(sliceLength: number): (input: T[]) => (T[])[];
1205412155
<summary><strong>R.splitEvery</strong> source</summary>
1205512156
1205612157
```javascript
12057-
export function splitEvery(sliceLength) {
12158+
export function splitEvery(sliceLength, strict = false) {
1205812159
return list => {
1205912160
if (sliceLength < 1) {
1206012161
throw new Error('First argument to splitEvery must be a positive integer')
@@ -12064,6 +12165,7 @@ export function splitEvery(sliceLength) {
1206412165
let counter = 0
1206512166

1206612167
while (counter < list.length) {
12168+
if (strict && counter + sliceLength > list.length) break;
1206712169
willReturn.push(list.slice(counter, (counter += sliceLength)))
1206812170
}
1206912171

@@ -14798,6 +14900,16 @@ describe('R.zipWith', () => {
1479814900
1479914901
## ❯ CHANGELOG
1480014902
14903+
11.2.0
14904+
14905+
- Add R.mergeDeep
14906+
14907+
- Add R.splitByStrict
14908+
14909+
11.1.1
14910+
14911+
- Fix `R.range`/`R.rangeDescending` when start and end match
14912+
1480114913
11.1.0
1480214914
1480314915
- Add `R.filterMap` - similar to Ruby `filter_map`

dist/rambda.cjs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,31 @@ function merge(target) {
11231123
Object.assign({}, target || {}, objectWithNewProps || {})
11241124
}
11251125

1126+
const isObject = (x) => type(x) === 'Object';
1127+
1128+
function mergeDeepFn(source, objectWithNewProps) {
1129+
return [source, objectWithNewProps].reduce((prev, obj) => {
1130+
Object.keys(obj).forEach((key) => {
1131+
const pVal = prev[key];
1132+
const oVal = obj[key];
1133+
1134+
if (isArray(pVal) && isArray(oVal)) {
1135+
prev[key] = oVal;
1136+
} else if (isObject(pVal) && isObject(oVal)) {
1137+
prev[key] = mergeDeepFn(pVal, oVal);
1138+
} else {
1139+
prev[key] = oVal;
1140+
}
1141+
});
1142+
1143+
return prev
1144+
}, {})
1145+
}
1146+
1147+
function mergeDeep(source) {
1148+
return (objectWithNewProps) => mergeDeepFn(source, objectWithNewProps)
1149+
}
1150+
11261151
function mergeTypes(x) {
11271152
return x
11281153
}
@@ -1559,7 +1584,8 @@ function random(min, max){
15591584
function range(a, b) {
15601585
const start = b === undefined ? 0 : a;
15611586
const end = b === undefined ? a : b;
1562-
if (end<= start) {
1587+
if (end === start) return [start]
1588+
if (end < start) {
15631589
return []
15641590
}
15651591
const len = end - start;
@@ -1568,7 +1594,8 @@ function range(a, b) {
15681594

15691595
function rangeDescending(start, b) {
15701596
const end = b === undefined ? 0 : b;
1571-
if (start <= end) {
1597+
if (start === end) return [start]
1598+
if (start < end) {
15721599
return []
15731600
}
15741601
const len = start - end;
@@ -1688,7 +1715,7 @@ function split(separator) {
16881715
return str => str.split(separator)
16891716
}
16901717

1691-
function splitEvery(sliceLength) {
1718+
function splitEvery(sliceLength, strict = false) {
16921719
return list => {
16931720
if (sliceLength < 1) {
16941721
throw new Error('First argument to splitEvery must be a positive integer')
@@ -1698,6 +1725,7 @@ function splitEvery(sliceLength) {
16981725
let counter = 0;
16991726

17001727
while (counter < list.length) {
1728+
if (strict && counter + sliceLength > list.length) break;
17011729
willReturn.push(list.slice(counter, (counter += sliceLength)));
17021730
}
17031731

@@ -2081,6 +2109,7 @@ exports.mapPropObject = mapPropObject;
20812109
exports.match = match;
20822110
exports.maxBy = maxBy;
20832111
exports.merge = merge;
2112+
exports.mergeDeep = mergeDeep;
20842113
exports.mergeTypes = mergeTypes;
20852114
exports.middle = middle;
20862115
exports.minBy = minBy;

dist/rambda.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,31 @@ function merge(target) {
11211121
Object.assign({}, target || {}, objectWithNewProps || {})
11221122
}
11231123

1124+
const isObject = (x) => type(x) === 'Object';
1125+
1126+
function mergeDeepFn(source, objectWithNewProps) {
1127+
return [source, objectWithNewProps].reduce((prev, obj) => {
1128+
Object.keys(obj).forEach((key) => {
1129+
const pVal = prev[key];
1130+
const oVal = obj[key];
1131+
1132+
if (isArray(pVal) && isArray(oVal)) {
1133+
prev[key] = oVal;
1134+
} else if (isObject(pVal) && isObject(oVal)) {
1135+
prev[key] = mergeDeepFn(pVal, oVal);
1136+
} else {
1137+
prev[key] = oVal;
1138+
}
1139+
});
1140+
1141+
return prev
1142+
}, {})
1143+
}
1144+
1145+
function mergeDeep(source) {
1146+
return (objectWithNewProps) => mergeDeepFn(source, objectWithNewProps)
1147+
}
1148+
11241149
function mergeTypes(x) {
11251150
return x
11261151
}
@@ -1557,7 +1582,8 @@ function random(min, max){
15571582
function range(a, b) {
15581583
const start = b === undefined ? 0 : a;
15591584
const end = b === undefined ? a : b;
1560-
if (end<= start) {
1585+
if (end === start) return [start]
1586+
if (end < start) {
15611587
return []
15621588
}
15631589
const len = end - start;
@@ -1566,7 +1592,8 @@ function range(a, b) {
15661592

15671593
function rangeDescending(start, b) {
15681594
const end = b === undefined ? 0 : b;
1569-
if (start <= end) {
1595+
if (start === end) return [start]
1596+
if (start < end) {
15701597
return []
15711598
}
15721599
const len = start - end;
@@ -1686,7 +1713,7 @@ function split(separator) {
16861713
return str => str.split(separator)
16871714
}
16881715

1689-
function splitEvery(sliceLength) {
1716+
function splitEvery(sliceLength, strict = false) {
16901717
return list => {
16911718
if (sliceLength < 1) {
16921719
throw new Error('First argument to splitEvery must be a positive integer')
@@ -1696,6 +1723,7 @@ function splitEvery(sliceLength) {
16961723
let counter = 0;
16971724

16981725
while (counter < list.length) {
1726+
if (strict && counter + sliceLength > list.length) break;
16991727
willReturn.push(list.slice(counter, (counter += sliceLength)));
17001728
}
17011729

@@ -2001,4 +2029,4 @@ function zipWith(fn, x) {
20012029
)
20022030
}
20032031

2004-
export { RAMBDA_DELAY, _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, delay, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterMap, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapChain, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, middle, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, random, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, sum, switcher, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith };
2032+
export { RAMBDA_DELAY, _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, delay, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterMap, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapChain, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeDeep, mergeTypes, middle, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, random, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, sum, switcher, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith };

0 commit comments

Comments
 (0)