Skip to content

Instantly share code, notes, and snippets.

@touhidrahman
Last active October 11, 2018 21:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save touhidrahman/d8c0120c7ef92ac5a1f09ce1cd6d1f02 to your computer and use it in GitHub Desktop.
Save touhidrahman/d8c0120c7ef92ac5a1f09ce1cd6d1f02 to your computer and use it in GitHub Desktop.
Flatten a javascript object in specified structure (see comment block)
/**
* Run file
*
* `tsc flatten.ts && node flatten.js`
*
* Given following object:
{
test: "test1",
same: "same",
nested: {
x: {
p: 3,
q: { r: 6 }
}
},
arr: [ 1, 2, 3],
arrObjs: [
{ y: "y"},
{ z: "a"}
]
}
*
* Should output:
*
[ { path: [ 'test' ], value: 'test1' },
{ path: [ 'same' ], value: 'same' },
{ path: [ 'arr' ], value: [ 1, 2, 3 ] },
{ path: [ 'arrObjs' ], value: [ [Object], [Object] ] },
{ path: [ 'nested', 'x', 'p' ], value: 3 },
{ path: [ 'nested', 'x', 'q', 'r' ], value: 6 } ]
*
*/
export interface PathValue {
path: Array<string>,
value: any,
}
export class Flattener {
isObject(obj: Object): boolean {
return typeof obj === 'object' && !Array.isArray(obj)
}
isPrimitiveOrArray(obj: Object): boolean {
return typeof obj !== 'object' || ( Array.isArray(obj) && obj.length > 0)
}
/**
* Input { a: { b: 1}}
* Return [ { path: 'a', value: {b:1} } ]
*/
flattenOneLevel(obj: Object, prePath: Array<string> = []): Array<PathValue> {
if (!this.isObject(obj)) return
const result: Array<PathValue> = []
Object.keys(obj).forEach(key => {
result.push({ path: [...prePath, key], value: obj[key] })
})
return result
}
flattenDeep(valueMap: Array<PathValue>): Array<PathValue> {
if (!valueMap) return
const result = valueMap.filter(
x => !!x.value && this.isPrimitiveOrArray(x.value)
)
valueMap
.filter(x => this.isObject(x.value))
.forEach(it => {
if (it.value)
this.flatten(it.value, it.path).forEach(y => result.push(y))
})
return result
}
flatten(obj: Object, prePath?: Array<string>): Array<PathValue> {
if (this.isObject(obj))
return this.flattenDeep(this.flattenOneLevel(obj, prePath))
}
}
/*******************
* Tests *
*******************/
let main = new Flattener()
const c = {
test: "test1",
same: "same",
nested: {
x: {
p: 3,
q: { r: 6 }
}
},
arr: [ 1, 2, 3],
arrObjs: [
{ y: "y"},
{ z: "a"}
]
}
const res = main.flatten(c)
console.log(res)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment