From 4a88c9ad12127f8d5f7d384e0a3aa8f84bfb3271 Mon Sep 17 00:00:00 2001 From: danrevah Date: Sun, 11 Dec 2016 01:48:59 +0200 Subject: [PATCH] feat(Invert & InvertBy): Added invert and invertBy pipes --- README.md | 34 +++++++++++++++++++++++-- src/app/pipes/object/index.ts | 6 ++++- src/app/pipes/object/invert-by.spec.ts | 35 ++++++++++++++++++++++++++ src/app/pipes/object/invert-by.ts | 20 +++++++++++++++ src/app/pipes/object/invert.spec.ts | 30 ++++++++++++++++++++++ src/app/pipes/object/invert.ts | 15 +++++++++++ 6 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 src/app/pipes/object/invert-by.spec.ts create mode 100644 src/app/pipes/object/invert-by.ts create mode 100644 src/app/pipes/object/invert.spec.ts create mode 100644 src/app/pipes/object/invert.ts 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}), {}); + } +}