Skip to content

Commit 1bccde5

Browse files
snowyusanjayaksaxena
authored andcommitted
feat: add .map() method
1 parent 107c03e commit 1bccde5

File tree

5 files changed

+163
-0
lines changed

5 files changed

+163
-0
lines changed

src/api/col-map.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Map for collections.
3+
* @param {function} f Call back function that is called on each item.
4+
* @param {number} start The start index in the collection.
5+
* @param {number} end The end index.
6+
* @param {function} itemFn Item function to create chainable-methods of the item.
7+
* @return {Array} The mapped collection.
8+
* @private
9+
*/
10+
var colMap = function ( f, start, end, itemFn ) {
11+
const result = [];
12+
for ( let k = start; k <= end; k += 1 ) {
13+
// Use relative indexing by adding `start` from `k`.
14+
result.push(f( itemFn( k ), ( k - start ) ));
15+
}
16+
return result;
17+
};
18+
19+
module.exports = colMap;

src/api/sel-map.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Map selected items.
3+
* @param {function} f Call back function that is called on each item.
4+
* @param {number[]} selection Array containing indexes to the selected items.
5+
* @param {function} itemFn Item function to create chainable-methods of the item.
6+
* @return {Array} Array of mapped items.
7+
* @private
8+
*/
9+
var selMap = function ( f, selection, itemFn ) {
10+
return selection.map( ( item, i ) => f( itemFn( item ), i ) );
11+
}; // selMap()
12+
13+
module.exports = selMap;

src/doc-v2.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ var selGetItemAt = require( './api/sel-get-item.js' );
4646
var colEach = require( './api/col-each.js' );
4747
var selEach = require( './api/sel-each.js' );
4848

49+
var colMap = require( './api/col-map.js' );
50+
var selMap = require( './api/sel-map.js' );
51+
4952
// **Filter** for collection & selection.
5053
var colFilter = require( './api/col-filter.js' );
5154
var selFilter = require( './api/sel-filter.js' );
@@ -185,6 +188,8 @@ var doc = function ( docData, addons ) {
185188
var api = Object.create( null );
186189
// Iterator.
187190
api.each = ( f ) => selEach( f, selectedTokens, itemToken );
191+
// Map.
192+
api.map = ( f ) => selMap( f, selectedTokens, itemToken );
188193
// Filter.
189194
api.filter = ( f ) => selFilter( f, selectedTokens, itemToken, colSelectedTokens );
190195
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
@@ -213,6 +218,8 @@ var doc = function ( docData, addons ) {
213218
var api = Object.create( null );
214219
// Iterator.
215220
api.each = ( f ) => colEach( f, start, end, itemToken );
221+
// Map.
222+
api.map = ( f ) => colMap( f, start, end, itemToken );
216223
// Filter.
217224
api.filter = ( f ) => colFilter( f, start, end, itemToken, colSelectedTokens );
218225
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
@@ -275,6 +282,8 @@ var doc = function ( docData, addons ) {
275282
var api = Object.create( null );
276283
// Iterator.
277284
api.each = ( f ) => selEach( f, selectedEntities, itemEntity );
285+
// Map.
286+
api.map = ( f ) => selMap( f, selectedEntities, itemEntity );
278287
// Filter.
279288
api.filter = ( f ) => selFilter( f, selectedEntities, itemEntity, colSelectedEntities );
280289
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
@@ -299,6 +308,8 @@ var doc = function ( docData, addons ) {
299308
var api = Object.create( null );
300309
// Iterator.
301310
api.each = ( f ) => colEach( f, 0, entities.length - 1, itemEntity );
311+
// Map.
312+
api.map = ( f ) => colMap( f, 0, entities.length - 1, itemEntity );
302313
// Filter.
303314
api.filter = ( f ) => colFilter( f, 0, entities.length - 1, itemEntity, colSelectedEntities );
304315
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
@@ -357,6 +368,8 @@ var doc = function ( docData, addons ) {
357368
var api = Object.create( null );
358369
// Iterator.
359370
api.each = ( f ) => selEach( f, selectedCustomEntities, itemCustomEntity );
371+
// Map.
372+
api.map = ( f ) => selMap( f, selectedCustomEntities, itemCustomEntity );
360373
// Filter.
361374
api.filter = ( f ) => selFilter( f, selectedCustomEntities, itemCustomEntity, colSelectedCustomEntities );
362375
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
@@ -381,6 +394,8 @@ var doc = function ( docData, addons ) {
381394
var api = Object.create( null );
382395
// Iterator.
383396
api.each = ( f ) => colEach( f, 0, customEntities.length - 1, itemCustomEntity );
397+
// Map.
398+
api.map = ( f ) => colMap( f, 0, customEntities.length - 1, itemCustomEntity );
384399
// Filter.
385400
api.filter = ( f ) => colFilter( f, 0, customEntities.length - 1, itemCustomEntity, colSelectedCustomEntities );
386401
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
@@ -438,6 +453,8 @@ var doc = function ( docData, addons ) {
438453
var api = Object.create( null );
439454
// Iterator.
440455
api.each = ( f ) => colEach( f, 0, sentences.length - 1, itemSentence );
456+
// Map.
457+
api.map = ( f ) => colMap( f, 0, sentences.length - 1, itemSentence );
441458
// Item at `k`th index. If `k` is outside valid range, return `undefined` like JS.
442459
api.itemAt = ( k ) => colGetItemAt( k, 0, ( sentences.length - 1 ), itemSentence );
443460
// Length of this collection.

test/apiA-specs.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ describe( 'APIs — A', function () {
171171
} );
172172
} );
173173

174+
it( '.map() iterator should go through each sentence', function () {
175+
var result = doc1.sentences().map( ( s ) => s.out() );
176+
expect( result ).to.deep.equal( as1 );
177+
178+
result = doc2.sentences().map( ( s ) => s.out() );
179+
expect( result ).to.deep.equal( as2 );
180+
} );
181+
174182
it( '.itemAt() should return correct sentence item', function () {
175183
const i11 = doc1.sentences().itemAt( 0 );
176184
expect( i11.out() ).to.equal( as1[ 0 ] );
@@ -189,6 +197,15 @@ describe( 'APIs — A', function () {
189197
} );
190198
} );
191199

200+
it( '.tokens().map() should return retlative token indexes — k', function () {
201+
var result = doc1.sentences().itemAt( 2 ).tokens().map( ( t ) => t.out() );
202+
console.log('🚀 ~ file: apiA-specs.js:202 ~ result:', result, d2s2t);
203+
expect(result).to.deep.equal( d1s2t );
204+
205+
result = doc2.sentences().itemAt( 2 ).tokens().map( ( t ) => t.out() );
206+
expect(result).to.deep.equal( d2s2t );
207+
} );
208+
192209
it( 'sentence.entities() should sentence wise entities correctly', function () {
193210
doc1.sentences().each( ( s, k ) => {
194211
expect( s.entities().out( its.detail ) ).deep.equal( d1SentenceWiseEntities[ k ] );
@@ -225,6 +242,14 @@ describe( 'APIs — A', function () {
225242
} );
226243
} );
227244

245+
it('.map() should return array of entities with their details', function () {
246+
const result1 = doc1.entities().map((e) => e.out(its.detail));
247+
expect(result1).to.deep.equal(ae1);
248+
249+
const result2 = doc2.entities().map((e) => e.out(its.detail));
250+
expect(result2).to.deep.equal(ae2);
251+
});
252+
228253
it( '.itemAt() should return correct entity item', function () {
229254
const i11 = doc1.entities().itemAt( 5 );
230255
expect( i11.out( its.detail ) ).to.deep.equal( ae1[ 5 ] );
@@ -283,6 +308,24 @@ describe( 'APIs — A', function () {
283308
expect( e.parentSentence().out() ).to.deep.equal( doc2.sentences().itemAt( es[ k ] ).out() );
284309
});
285310
} );
311+
312+
it('entities().map() --- sentence() should point correct sentence for each entity', function () {
313+
// Maps entity's index to sentence's index.
314+
const es = [ 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2 ];
315+
316+
const expectedSentencesForDoc1 = es.map((sentenceIdx) =>
317+
doc1.sentences().itemAt(sentenceIdx).out()
318+
);
319+
const expectedSentencesForDoc2 = es.map((sentenceIdx) =>
320+
doc2.sentences().itemAt(sentenceIdx).out()
321+
);
322+
323+
const actualSentencesForDoc1 = doc1.entities().map((e) => e.parentSentence().out());
324+
const actualSentencesForDoc2 = doc2.entities().map((e) => e.parentSentence().out());
325+
326+
expect(actualSentencesForDoc1).to.deep.equal(expectedSentencesForDoc1);
327+
expect(actualSentencesForDoc2).to.deep.equal(expectedSentencesForDoc2);
328+
});
286329
} ); // doc.entities() API
287330

288331
describe( 'doc.tokens() API', function () {
@@ -367,6 +410,20 @@ describe( 'APIs — A', function () {
367410
} );
368411
} );
369412

413+
it('.map() should correctly map filtered numbers', function () {
414+
const mappedF1 = doc1.tokens()
415+
.filter((t) => t.out(its.type) === 'number')
416+
.map((t) => t.out());
417+
418+
expect(mappedF1).to.deep.equal(f1num);
419+
420+
const mappedF2 = doc2.tokens()
421+
.filter((t) => t.out(its.type) === 'number')
422+
.map((t) => t.out());
423+
424+
expect(mappedF2).to.deep.equal(f2num);
425+
});
426+
370427
it( '.itemAt() should return correct item from filtered numebrs', function () {
371428
const i1 = doc1.tokens()
372429
.filter( ( t ) => ( t.out( its.type ) === 'number' ) )

test/apiB-specs.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,23 @@ describe( 'APIs — B', function () {
227227
}
228228
} ); // .each() method via .itmAt()
229229

230+
it('.map() method via .itemAt()', function () {
231+
const mappedSentences = [];
232+
233+
for (let i = 0; i < docs.length; i += 1) {
234+
const doc = docs[i];
235+
const sentencesFromMap = doc.sentences().map((s, k) => {
236+
expect(s.out()).to.deep.equal(doc.sentences().itemAt(k).out());
237+
expect(s.out()).to.deep.equal(sentences[i][k]);
238+
return s.out();
239+
});
240+
241+
mappedSentences.push(sentencesFromMap);
242+
}
243+
244+
expect(mappedSentences).to.deep.equal(sentences);
245+
});
246+
230247
it( '.length() method', function () {
231248
for ( let i = 0; i < docs.length; i += 1 ) {
232249
expect( docs[ i ].sentences().length() ).to.equal( sentences[ i ].length );
@@ -305,6 +322,15 @@ describe( 'APIs — B', function () {
305322
} // for
306323
} ); // .each() method
307324

325+
it('.map() method', function () {
326+
for (let i = 0; i < docs.length; i += 1) {
327+
const doc = docs[i];
328+
const result = doc.entities().map((e) => (e ? e.out() : undefined));
329+
330+
expect(result).to.deep.equal([].concat([], ...entities[i]));
331+
}
332+
});
333+
308334
it( '.filter() method', function () {
309335
expect( docs[ 0 ].entities().filter( dates ).out() ).to.deep.equal( d0[ DATE ] );
310336
expect( docs[ 0 ].entities().filter( cardinals ).out() ).to.deep.equal( d0[ CARDINAL ] );
@@ -348,6 +374,11 @@ describe( 'APIs — B', function () {
348374
} );
349375
} ); // .each() method
350376

377+
it('.map() method', function () {
378+
const result = selOfCardinals.map((e) => e.out());
379+
expect(result).to.deep.equal(d0[CARDINAL]);
380+
});
381+
351382
it( '.filter() method', function () {
352383
expect( selOfCardinals.filter( ( e ) => ( e.out() === d0[ CARDINAL ][ 0 ] ) ).out() ).to.deep.equal( d0[ CARDINAL ].slice( 0, 1 ) );
353384
} ); // .filter() method
@@ -420,6 +451,15 @@ describe( 'APIs — B', function () {
420451
} // for
421452
} ); // .each() method
422453

454+
it('.map() method', function () {
455+
for (let i = 0; i < docs.length; i += 1) {
456+
const doc = docs[i];
457+
const result = doc.customEntities().map((e) => (e ? e.out() : undefined));
458+
459+
expect(result).to.deep.equal([].concat([], ...customEntities[i]));
460+
}
461+
});
462+
423463
it( '.filter() method', function () {
424464
expect( docs[ 0 ].customEntities().filter( fighters ).out() ).to.deep.equal( d0ce.fighters );
425465
expect( docs[ 0 ].customEntities().filter( orgs ).out() ).to.deep.equal( d0ce.orgs );
@@ -535,6 +575,15 @@ describe( 'APIs — B', function () {
535575
} // for
536576
} ); // .each() method
537577

578+
it('.map() method', function () {
579+
for (let i = 0; i < docs.length; i += 1) {
580+
const doc = docs[i];
581+
const result = doc.tokens().map((t) => (t ? t.out() : undefined));
582+
583+
expect(result).to.deep.equal([].concat([], ...tokens[i]));
584+
}
585+
});
586+
538587
it( '.filter() method', function () {
539588
expect( docs[ 0 ].tokens().filter( words ).out() ).to.deep.equal( d0words );
540589
expect( docs[ 1 ].tokens().filter( words ).out() ).to.deep.equal( d1words );
@@ -583,6 +632,14 @@ describe( 'APIs — B', function () {
583632
} );
584633
} ); // .each() method
585634

635+
it('.map() method', function () {
636+
const result0 = selOfWords0.map((e) => e.out());
637+
const result1 = selOfWords1.map((e) => e.out());
638+
639+
expect(result0).to.deep.equal(d0words);
640+
expect(result1).to.deep.equal(d1words);
641+
});
642+
586643
it( '.filter() method', function () {
587644
expect( selOfWords0.filter( ( t ) => ( t.out().length < 3 ) ).out() ).to.deep.equal( [ 'by', 'is', 'by' ] );
588645
expect( selOfWords1.filter( ( t ) => ( t.out().length < 3 ) ).out() ).to.deep.equal( [ 'me', 'up', 'on', 'my', 'we' ] );

0 commit comments

Comments
 (0)