diff --git a/README.md b/README.md
index 0baa25db..b5018e10 100644
--- a/README.md
+++ b/README.md
@@ -43,6 +43,9 @@
- [every](#every)
- [some](#some)
- [sample](#sample)
+ - [groupBy](#groupBy)
+ - [keys](#keys)
+ - [values](#values)
- [Math](#Math)
- [min](#min)
- [max](#max)
@@ -519,6 +522,48 @@ API: `array | sample: [amount | default = 1]`
{{ [1, 2, 3, 4] | sample: 2 }}
```
+### groupBy
+
+Returns object of grouped by items by discriminator
+
+API: `array | groupBy: [string | Function]`
+
+```javascript
+import {GroupByPipe} from 'ng2-pipes/src/app/pipes/array/group-by';
+
+@Component({
+ // ...
+ providers: [GroupByPipe]
+})
+export class AppComponent {
+ constructor(private groupByPipe: GroupByPipe) {
+ // ..
+ const arrayObject = [{elm: 'foo', value: 0}, {elm: 'bar', value: 1}, {elm: 'foo', value: 2}];
+ const groupedObject = groupByPipe.transform(arrayObject, 'elm'));
+ // `groupedObject` -> Contains: {foo: [{elm: 'foo', value: 0}, {elm: 'foo', value: 2}], bar: [{elm: 'bar', value: 1}]}
+ }
+```
+
+### keys
+
+Returns array of object keys
+
+API: `object | keys`
+
+```html
+{{ {foo: 1, bar: 2} | keys }}
+```
+
+### values
+
+Returns array of object values
+
+API: `object | values`
+
+```html
+{{ {foo: 1, bar: 2} | values }}
+```
+
## Math
### min
diff --git a/src/app/pipes/array/group-by.spec.ts b/src/app/pipes/array/group-by.spec.ts
new file mode 100644
index 00000000..c768598f
--- /dev/null
+++ b/src/app/pipes/array/group-by.spec.ts
@@ -0,0 +1,39 @@
+import {GroupByPipe} from './group-by';
+
+describe('GroupByPipe', () => {
+ let pipe: GroupByPipe;
+
+ beforeEach(() => {
+ pipe = new GroupByPipe();
+ });
+
+
+ it('should create an instance', () => {
+ expect(pipe).toBeTruthy();
+ });
+
+ it('should not change anything if not array', () => {
+ expect(pipe.transform('foo')).toEqual('foo');
+ expect(pipe.transform(null)).toEqual(null);
+ expect(pipe.transform(undefined)).toEqual(undefined);
+ expect(pipe.transform(42)).toEqual(42);
+ expect(pipe.transform({foo: 1, bar: 2})).toEqual({foo: 1, bar: 2});
+ });
+
+ it('group on discriminator', () => {
+ const arrayWithDiscriminator = [{key: 'foo'}, {key: 'bar'}, {key: 'foo'}, {key: 'bar'}];
+ const result = pipe.transform(arrayWithDiscriminator, 'key');
+ expect(result).toEqual({
+ foo: [{key: 'foo'}, {key: 'foo'}],
+ bar: [{key: 'bar'}, {key: 'bar'}]
+ });
+ });
+ it('allow function to be used as discriminator', () => {
+ const arrayWithDiscriminator = [{key: 'foo'}, {key: 'bar'}, {key: 'foo'}, {key: 'bar'}];
+ const result = pipe.transform(arrayWithDiscriminator, _ => _['key']);
+ expect(result).toEqual({
+ foo: [{key: 'foo'}, {key: 'foo'}],
+ bar: [{key: 'bar'}, {key: 'bar'}]
+ });
+ });
+});
diff --git a/src/app/pipes/array/group-by.ts b/src/app/pipes/array/group-by.ts
new file mode 100644
index 00000000..6bb37f2c
--- /dev/null
+++ b/src/app/pipes/array/group-by.ts
@@ -0,0 +1,26 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import GeneralHelper from '../helpers/helpers';
+
+@Pipe({name: 'groupBy'})
+export class GroupByPipe implements PipeTransform {
+
+ transform(arr: any, ...args: any[]): any {
+ if (!Array.isArray(arr)) {
+ return arr;
+ }
+
+ return this.groupBy(arr, args[0]);
+ }
+
+ private groupBy(list: any[], discriminator: Function | string) {
+ return list.reduce((acc, payload) => {
+ const key = GeneralHelper.isFunction(discriminator)
+ ? (discriminator)(payload)
+ : payload[discriminator];
+
+ return acc[key] = Array.isArray(acc[key])
+ ? acc[key].concat([payload])
+ : [payload], acc;
+ }, {});
+ }
+}
diff --git a/src/app/pipes/array/groupBy.spec.ts b/src/app/pipes/array/groupBy.spec.ts
deleted file mode 100644
index 3616f220..00000000
--- a/src/app/pipes/array/groupBy.spec.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { GroupByPipe } from './groupBy';
-
-describe('Pipe: GroupBy', () => {
- it('create an instance', () => {
- let pipe = new GroupByPipe();
- expect(pipe).toBeTruthy();
- });
-
-});
-describe('GroupByPipe', () => {
- let pipe: GroupByPipe;
-
- beforeEach(() => {
- pipe = new GroupByPipe();
- });
-
- it('should not change anything if not array', () => {
- expect(pipe.transform('foo')).toEqual('foo');
- expect(pipe.transform(null)).toEqual(null);
- expect(pipe.transform(undefined)).toEqual(undefined);
- expect(pipe.transform(42)).toEqual(42);
- expect(pipe.transform({ foo: 1, bar: 2 })).toEqual({ foo: 1, bar: 2 });
- });
-
- it('group on discriminator', () => {
- let arrayWithDiscriminator = [
- {
- key: 'value0'
- },
- {
- key: 'value1'
- },
- {
- key: 'value0'
- },
- {
- key: 'value1'
- }
- ];
- let result = pipe.transform(arrayWithDiscriminator, 'key');
- expect(result).toEqual([ [ 'value0', [ { key: 'value0' }, { key: 'value0' }] ], [ 'value1', [ { key: 'value1' }, { key: 'value1' }] ] ]);
- });
- it('allow function to be used as discriminator', () => {
- let arrayWithDiscriminator = [
- {
- key: 'value0'
- },
- {
- key: 'value1'
- },
- {
- key: 'value0'
- },
- {
- key: 'value1'
- }
- ];
- let result = pipe.transform(arrayWithDiscriminator, (instance: any) => { return instance[ 'key' ] });
- expect(result).toEqual([ [ 'value0', [ { key: 'value0' }, { key: 'value0' }] ], [ 'value1', [ { key: 'value1' }, { key: 'value1' }] ] ]);
- });
-});
diff --git a/src/app/pipes/array/groupBy.ts b/src/app/pipes/array/groupBy.ts
deleted file mode 100644
index 99ca52f6..00000000
--- a/src/app/pipes/array/groupBy.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Pipe, PipeTransform } from '@angular/core';
-
-@Pipe({
- name: 'groupBy'
-})
-export class GroupByPipe implements PipeTransform {
- groupBy = (list: any[], discriminator: Function | string) => {
- let map = list.reduce((acc, payload, i) => {
- let key = discriminator instanceof Function ? discriminator(payload) : payload[ discriminator ];
- return Object.assign({}, acc, {
- [ key ]: acc[ key ] instanceof Array ? acc[ key ].concat([ payload ]) : [ payload ]
- });
- }, {});
- return Object.keys(map).map((key: string) => [ key, map[ key ] ]);
- }
- transform(arr: any, ...args: any[]): any {
- if (!Array.isArray(arr)) {
- return arr;
- }
- return this.groupBy(arr, args[ 0 ]);
- }
-
-}
\ No newline at end of file
diff --git a/src/app/pipes/array/index.ts b/src/app/pipes/array/index.ts
index 6fc10c08..60cad2d2 100644
--- a/src/app/pipes/array/index.ts
+++ b/src/app/pipes/array/index.ts
@@ -13,13 +13,15 @@ import { ShufflePipe } from './shuffle';
import { EveryPipe } from './every';
import { SomePipe } from './some';
import { SamplePipe } from './sample';
-import { GroupByPipe } from './groupBy';
+import { GroupByPipe } from './group-by';
+import { KeysPipe } from './keys';
+import { ValuesPipe } from './values';
import { NgModule } from '@angular/core';
const ARRAY_PIPES = [
DiffPipe, FlattenPipe, InitialPipe, IntersectionPipe, ReversePipe, TailPipe,
TrurthifyPipe, UnionPipe, UniquePipe, WithoutPipe, PluckPipe, ShufflePipe,
- EveryPipe, SomePipe, SamplePipe, GroupByPipe
+ EveryPipe, SomePipe, SamplePipe, GroupByPipe, KeysPipe, ValuesPipe
];
@NgModule({
@@ -44,4 +46,6 @@ export * from './shuffle';
export * from './every';
export * from './some';
export * from './sample';
-export * from './groupBy';
+export * from './keys';
+export * from './values';
+export * from './group-by';
diff --git a/src/app/pipes/array/keys.spec.ts b/src/app/pipes/array/keys.spec.ts
new file mode 100644
index 00000000..4674d7b4
--- /dev/null
+++ b/src/app/pipes/array/keys.spec.ts
@@ -0,0 +1,23 @@
+import {KeysPipe} from './keys';
+
+describe('Keys Pipe', () => {
+ let pipe: KeysPipe;
+
+ beforeEach(() => {
+ pipe = new KeysPipe();
+ });
+
+ 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 array of keys', () => {
+ expect(pipe.transform({})).toEqual([]);
+ expect(pipe.transform({foo: 'bar'})).toEqual(['foo']);
+ expect(pipe.transform({foo: 1, bar: 42})).toEqual(['foo', 'bar']);
+ });
+});
diff --git a/src/app/pipes/array/keys.ts b/src/app/pipes/array/keys.ts
new file mode 100644
index 00000000..c52a3b1c
--- /dev/null
+++ b/src/app/pipes/array/keys.ts
@@ -0,0 +1,14 @@
+import {PipeTransform, Pipe} from '@angular/core';
+import GeneralHelper from '../helpers/helpers';
+
+@Pipe({name: 'keys'})
+export class KeysPipe implements PipeTransform {
+
+ transform(obj: any): any[] {
+ if (Array.isArray(obj) || !GeneralHelper.isObject(obj)) {
+ return obj;
+ }
+
+ return Object.keys(obj);
+ }
+}
diff --git a/src/app/pipes/array/values.spec.ts b/src/app/pipes/array/values.spec.ts
new file mode 100644
index 00000000..6a53f242
--- /dev/null
+++ b/src/app/pipes/array/values.spec.ts
@@ -0,0 +1,23 @@
+import {ValuesPipe} from './values';
+
+describe('Values Pipe', () => {
+ let pipe: ValuesPipe;
+
+ beforeEach(() => {
+ pipe = new ValuesPipe();
+ });
+
+ 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 array of values', () => {
+ expect(pipe.transform({})).toEqual([]);
+ expect(pipe.transform({foo: 'bar'})).toEqual(['bar']);
+ expect(pipe.transform({foo: 1, bar: 42})).toEqual([1, 42]);
+ });
+});
diff --git a/src/app/pipes/array/values.ts b/src/app/pipes/array/values.ts
new file mode 100644
index 00000000..5ef9feb4
--- /dev/null
+++ b/src/app/pipes/array/values.ts
@@ -0,0 +1,14 @@
+import {PipeTransform, Pipe} from '@angular/core';
+import GeneralHelper from '../helpers/helpers';
+
+@Pipe({name: 'values'})
+export class ValuesPipe implements PipeTransform {
+
+ transform(obj: any): any[] {
+ if (Array.isArray(obj) || !GeneralHelper.isObject(obj)) {
+ return obj;
+ }
+
+ return Object.keys(obj).map(k => obj[k]);
+ }
+}
diff --git a/src/app/pipes/helpers/helpers.ts b/src/app/pipes/helpers/helpers.ts
index 3b2e6f87..ef659e72 100644
--- a/src/app/pipes/helpers/helpers.ts
+++ b/src/app/pipes/helpers/helpers.ts
@@ -1,9 +1,13 @@
export default class GeneralHelper {
- static isUndefined(value) {
+ static isUndefined(value: any) {
return typeof value === 'undefined';
}
+ static isFunction(value: any) {
+ return typeof value === 'function';
+ }
+
static isNumber(value: any) {
return typeof value === 'number';
}
@@ -12,6 +16,10 @@ export default class GeneralHelper {
return typeof value === 'string';
}
+ static isObject(value: any) {
+ return value !== null && typeof value === 'object';
+ }
+
static isNumberFinite(value: any) {
return GeneralHelper.isNumber(value) && isFinite(value);
}