Created
January 16, 2019 20:13
-
-
Save stalniy/c559830d2cbc881798098f28b98122cd to your computer and use it in GitHub Desktop.
Custom pick with support for arrays using asterisk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function get(object, path) { | |
const fields = Array.isArray(path) ? path : path.split('.') | |
let cursor = object | |
for (let i = 0; i < fields.length; i++) { | |
if (fields[i] === '*') { | |
// TODO: validation of cursor being an array | |
const newPath = fields.slice(i + 1) | |
return cursor.map(item => get(item, newPath)) | |
} else { | |
cursor = cursor[fields[i]] | |
} | |
} | |
return cursor | |
} | |
function set(object, path, value) { | |
const fields = Array.isArray(path) ? path : path.split('.') | |
let cursor = object | |
let prevCursor | |
for (let i = 0; i < fields.length - 1; i++) { | |
const field = fields[i] | |
if (field === '*') { | |
const newPath = fields.slice(i + 1) | |
// TODO: validation of value being an array | |
const newValue = value.map((val, index) => set(cursor[index] || {}, newPath, val)) | |
if (i > 0) { | |
prevCursor[fields[i - 1]] = newValue | |
} else { | |
return newValue | |
} | |
return object | |
} else { | |
prevCursor = cursor | |
cursor = cursor[field] = cursor[field] || {} | |
} | |
} | |
const lastField = fields[fields.length - 1] | |
if (Array.isArray(cursor)) { | |
cursor.forEach(item => item[lastField] = value) | |
} else { | |
cursor[lastField] = value | |
} | |
return object | |
} | |
function pick(object, paths) { | |
return paths.reduce((slice, path) => { | |
const value = get(object, path) | |
if (typeof value !== 'undefined') { | |
set(slice, path, value) | |
} | |
return slice | |
}, {}) | |
} | |
const payload = { | |
title: 'test', | |
nested: { | |
field: 3, | |
another: 4 | |
}, | |
children: [ | |
{ | |
field: 1, | |
another: 2, | |
obj: { | |
title: 'test1', | |
nested: [ | |
{ a: 1, c: 3 }, | |
{ a: 3 } | |
] | |
} | |
}, | |
{ | |
field: 2, | |
another: 3, | |
obj: { | |
title: 'test2', | |
nested: [ | |
{ a: 2, b: 2 } | |
] | |
} | |
} | |
] | |
} | |
console.log(pick(payload, [ | |
'title', | |
'children.*.field', // asterisk mean "retrieve subpath from every array item. So, here we take `field` of every item inside `payload.children` array | |
'children.*.obj.nested.*.a' | |
])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment