Skip to content

Commit

Permalink
feat(Array Filters): Group by & values & keys
Browse files Browse the repository at this point in the history
  • Loading branch information
danrevah committed Dec 9, 2016
1 parent 5ba7c15 commit d8c145b
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 88 deletions.
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
- [every](#every)
- [some](#some)
- [sample](#sample)
- [groupBy](#groupBy)
- [keys](#keys)
- [values](#values)
- [Math](#Math)
- [min](#min)
- [max](#max)
Expand Down Expand Up @@ -519,6 +522,48 @@ API: `array | sample: [amount | default = 1]`
<p>{{ [1, 2, 3, 4] | sample: 2 }}</p> <!-- Output: "[4, 3]" -->
```

### 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
<p>{{ {foo: 1, bar: 2} | keys }}</p> <!-- Output: "['foo', 'bar']" -->
```

### values

Returns array of object values

API: `object | values`

```html
<p>{{ {foo: 1, bar: 2} | values }}</p> <!-- Output: "[1, 2]" -->
```

## Math

### min
Expand Down
39 changes: 39 additions & 0 deletions src/app/pipes/array/group-by.spec.ts
Original file line number Diff line number Diff line change
@@ -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'}]
});
});
});
26 changes: 26 additions & 0 deletions src/app/pipes/array/group-by.ts
Original file line number Diff line number Diff line change
@@ -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)
? (<Function>discriminator)(payload)
: payload[<string>discriminator];

return acc[key] = Array.isArray(acc[key])
? acc[key].concat([payload])
: [payload], acc;
}, {});
}
}
61 changes: 0 additions & 61 deletions src/app/pipes/array/groupBy.spec.ts

This file was deleted.

23 changes: 0 additions & 23 deletions src/app/pipes/array/groupBy.ts

This file was deleted.

10 changes: 7 additions & 3 deletions src/app/pipes/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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';
23 changes: 23 additions & 0 deletions src/app/pipes/array/keys.spec.ts
Original file line number Diff line number Diff line change
@@ -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']);
});
});
14 changes: 14 additions & 0 deletions src/app/pipes/array/keys.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
23 changes: 23 additions & 0 deletions src/app/pipes/array/values.spec.ts
Original file line number Diff line number Diff line change
@@ -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]);
});
});
14 changes: 14 additions & 0 deletions src/app/pipes/array/values.ts
Original file line number Diff line number Diff line change
@@ -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]);
}
}
10 changes: 9 additions & 1 deletion src/app/pipes/helpers/helpers.ts
Original file line number Diff line number Diff line change
@@ -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';
}
Expand All @@ -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);
}
Expand Down

0 comments on commit d8c145b

Please sign in to comment.