diff --git a/README.md b/README.md index 97fabaf2..e58c02a1 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - [Installation](#installation) - [Changelog](#changelog) - [Contributing](#contributing) - - [String](#String) + - [String](#string) - [repeat](#repeat) - [scan](#scan) - [shorten](#shorten) @@ -49,6 +49,8 @@ - [values](#values) - [pairs](#pairs) - [pick](#pick) + - [invert](#invert) + - [invertby](#invertby) - [Math](#math) - [min](#min) - [max](#max) @@ -61,7 +63,7 @@ - [degrees](#degrees) - [radians](#radians) - [bytes](#bytes) - - [Boolean](#Boolean) + - [Boolean](#boolean) - [isNull](#isnull) - [isDefined](#isdefined) - [isUndefined](#isundefined) @@ -590,6 +592,34 @@ API: `object | pick: [key | string]]`
{{ {foo: 1, bar: 2} | pick: 'foo': 'bar' }}
``` +### invert + +Returns object with inverted keys and values. in case of equal values, subsequent values overwrite property assignments of previous values. + +API: `object | invert` + +```html +{{ {foo: 1, bar: 2} | invert }}
+``` + +### invertBy + +Returns object with inverted keys and values. in case of equal values, will add to an array. + +API: `object | invertBy: [Function | optional]` + +```typescript +this.cb = (value): string => { + return `name_${value}`; +}; +``` + +```html +{{ {foo: 1, bar: 2} | invertBy }}
+{{ {foo: 1, bar: 2} | invertBy: cb }}
+{{ {a: 1, b: 2, c: 1, d: 2} | invertBy }}
+``` + ## Math ### min diff --git a/src/app/pipes/object/index.ts b/src/app/pipes/object/index.ts index dbc4d2c5..6c879862 100644 --- a/src/app/pipes/object/index.ts +++ b/src/app/pipes/object/index.ts @@ -2,10 +2,12 @@ import { KeysPipe } from './keys'; import { ValuesPipe } from './values'; import { PairsPipe } from './pairs'; import { PickPipe } from './pick'; +import { InvertPipe } from './invert'; +import { InvertByPipe } from './invert-by'; import { NgModule } from '@angular/core'; const OBJECT_PIPES = [ - KeysPipe, ValuesPipe, PairsPipe, PickPipe + KeysPipe, ValuesPipe, PairsPipe, PickPipe, InvertPipe, InvertByPipe ]; @NgModule({ @@ -19,3 +21,5 @@ export * from './keys'; export * from './values'; export * from './pairs'; export * from './pick'; +export * from './invert'; +export * from './invert-by'; diff --git a/src/app/pipes/object/invert-by.spec.ts b/src/app/pipes/object/invert-by.spec.ts new file mode 100644 index 00000000..8fb98a4c --- /dev/null +++ b/src/app/pipes/object/invert-by.spec.ts @@ -0,0 +1,35 @@ +import {InvertByPipe} from './invert-by'; + +describe('InvertBy Pipe', () => { + let pipe: InvertByPipe; + + beforeEach(() => { + pipe = new InvertByPipe(); + }); + + it('should keep the element the same way if its not an object', () => { + expect(pipe.transform([1, 2, 3])).toEqual([1, 2, 3]); + expect(pipe.transform([])).toEqual([]); + expect(pipe.transform('foo')).toEqual('foo'); + expect(pipe.transform(null)).toEqual(null); + expect(pipe.transform(undefined)).toEqual(undefined); + }); + + it('should return inverted values / keys object', () => { + expect(pipe.transform({})).toEqual({}); + expect(pipe.transform({foo: 'bar'})).toEqual({bar: ['foo']}); + expect(pipe.transform({foo: 1, bar: 42})).toEqual({1: ['foo'], 42: ['bar']}); + + expect(pipe.transform({}, _ => `name_${_}`)).toEqual({}); + expect(pipe.transform({foo: 'bar'}, _ => `name_${_}`)).toEqual({name_bar: ['foo']}); + expect(pipe.transform({foo: 1, bar: 42}, _ => `name_${_}`)).toEqual({name_1: ['foo'], name_42: ['bar']}); + }); + + it('should return inverted values / keys subsequent values override previous value', () => { + expect(pipe.transform({a: 1, b: 2, c: 1})).toEqual({1: ['a', 'c'], 2: ['b']}); + expect(pipe.transform({a: 1, b: 2, c: 1, d: 2, e: 3})).toEqual({1: ['a','c'], 2: ['b','d'], 3: ['e']}); + + expect(pipe.transform({a: 1, b: 2, c: 1}, _ => `name_${_}`)).toEqual({name_1: ['a', 'c'], name_2: ['b']}); + expect(pipe.transform({a: 1, b: 2, c: 1, d: 2, e: 3}, _ => `name_${_}`)).toEqual({name_1: ['a','c'], name_2: ['b','d'], name_3: ['e']}); + }); +}); diff --git a/src/app/pipes/object/invert-by.ts b/src/app/pipes/object/invert-by.ts new file mode 100644 index 00000000..e0aefeaa --- /dev/null +++ b/src/app/pipes/object/invert-by.ts @@ -0,0 +1,20 @@ +import {PipeTransform, Pipe} from '@angular/core'; +import GeneralHelper from '../helpers/helpers'; + +@Pipe({name: 'invertBy'}) +export class InvertByPipe implements PipeTransform { + + transform(obj: any, cb: Function = null): Object { + if (Array.isArray(obj) || !GeneralHelper.isObject(obj)) { + return obj; + } + + return Object.keys(obj) + .reduce((o, k) => { + const key = cb ? cb(obj[k]) : obj[k]; + return Array.isArray(o[key]) + ? (o[key].push(k), o) + : Object.assign(o, {[key]: [k]}); + }, {}); + } +} diff --git a/src/app/pipes/object/invert.spec.ts b/src/app/pipes/object/invert.spec.ts new file mode 100644 index 00000000..b423279a --- /dev/null +++ b/src/app/pipes/object/invert.spec.ts @@ -0,0 +1,30 @@ +import {InvertPipe} from './invert'; + +describe('Invert Pipe', () => { + let pipe: InvertPipe; + + beforeEach(() => { + pipe = new InvertPipe(); + }); + + it('should keep the element the same way if its not an object', () => { + expect(pipe.transform([1, 2, 3])).toEqual([1, 2, 3]); + expect(pipe.transform([])).toEqual([]); + expect(pipe.transform('foo')).toEqual('foo'); + expect(pipe.transform(null)).toEqual(null); + expect(pipe.transform(undefined)).toEqual(undefined); + }); + + it('should return inverted values / keys object', () => { + expect(pipe.transform({})).toEqual({}); + expect(pipe.transform({foo: 'bar'})).toEqual({bar: 'foo'}); + expect(pipe.transform({foo: 1, bar: 42})).toEqual({1: 'foo', 42: 'bar'}); + expect(pipe.transform({foo: [1, 2], bar: 42})).toEqual({'1,2': 'foo', 42: 'bar'}); + expect(pipe.transform({foo: {a: 1, b: 2}, bar: 42})).toEqual({'[object Object]': 'foo', 42: 'bar'}); + }); + + it('should return inverted values / keys subsequent values override previous value', () => { + expect(pipe.transform({a: 1, b: 2, c: 1})).toEqual({1: 'c', 2: 'b'}); + expect(pipe.transform({a: 1, b: 2, c: 1, d: 2, e: 3})).toEqual({1: 'c', 2: 'd', 3: 'e'}); + }); +}); diff --git a/src/app/pipes/object/invert.ts b/src/app/pipes/object/invert.ts new file mode 100644 index 00000000..c29afe81 --- /dev/null +++ b/src/app/pipes/object/invert.ts @@ -0,0 +1,15 @@ +import {PipeTransform, Pipe} from '@angular/core'; +import GeneralHelper from '../helpers/helpers'; + +@Pipe({name: 'invert'}) +export class InvertPipe implements PipeTransform { + + transform(obj: any): Object { + if (Array.isArray(obj) || !GeneralHelper.isObject(obj)) { + return obj; + } + + return Object.keys(obj) + .reduce((o, k) => Object.assign(o, {[obj[k]]: k}), {}); + } +}