Utility Methods for working with Arrays / Lists
similar to module:group, this is not meant to be exhaustive, only the ones commonly used.
- Generate Array
- array.size(size, default) - generate array of a specific size and CONSISTENT default value
- array.arrange(size, start, step) - generate array of a size, and INCREASING default value
- array.arrangeMulti(n, m, ...) - generate a multi-dimensional array
- array.clone(array) - deep clones arrays
- Sorting
- array.createSort(sortIndex, sortIndex, ...) - generates a sorting function
- array.SORT_ASCENDING - common ascending sorting function for array.sort()
- array.SORT_DESCENDING - common descending sorting function for array.sort()
- array.indexify - identify sections within a 1d array to create a hierarchy.
- Rearrange Array
- array.reshape - reshapes an array to a size of rows and columns
- array.transpose - transposes (flips - the array along the diagonal)
- Picking Values
- array.peekFirst - peeks at the first value in the list
- array.peekLast - peeks at the last value in the list
- array.pickRows - picks a row from a 2d array
- array.pickColumns - picks a column from a 2d array
- array.pick - picks either/or rows and columns
- Extracting Array Values
- array.extract - synonym to array.pick to pick either a row or column from an array
- array.multiLineSubstr - Extract Substr from a multi-line string or array of strings
- array.multiLineSubstring - Extract Substring from a multi-line string or array of strings
- array.multiStepReduce - Performs reduce, and returns the value of reduce at each step
- Applying a value
- array.applyArrayValue - applies a value deeply into an array safely
- array.applyArrayValues - applies a value / multiple values deeply into an array safely
- Understanding Values
- array.isMultiDimensional - determines if an array is multi-dimensional
- Custom Iterators
- PeekableArrayIterator - Iterator that lets you peek ahead while not moving the iterator.
- Iterating over values
- delayedFn - Similar to Function.bind() - you specify a function and arguments only to be called when you ask
- chainFunctions - Chain a set of functions to be called one after another.
- asyncWaitAndChain - Chains a set of functions to run one after another, but with a delay between.
Classes
Members
(static) extract
- See:
-
- module:array.pickRows - picking rows
- module:array.pickColumns - picking columns
Convenience function for picking specific rows and columns from a 2d array.
Alias of array.pick
Please also see Danfo.js for working with DataFrames.
Example
data = [
['john', 23, 'purple'],
['jane', 32, 'red'],
['ringo', 27, 'green']
];
utils.array.pick(data, {rows: [0, 1]});
//-- [['john', 23, 'purple'], ['jane', 32, 'red']];
utils.array.pick(data, {columns: [0, 2]});
//-- [['john', 'purple'], ['jane', 'red'], ['ringo', 'green']];
utils.array.pick(data, {rows:[0, 1], columns:[0, 2]});
//-- [['john', 'purple'], ['jane', 'red']];
Methods
(static) SORT_ASCENDING()
Simple ascending sort function
Example
[3,5,1,2,4].sort(utils.sort.SIMPLE_ASCENDING))
//
[1,2,3,4,5]
(static) SORT_DESCENDING()
Simple descending sort function
Example
[3,5,1,2,4].sort(utils.sort.SIMPLE_ASCENDING))
//
[5,4,3,2,1]
(static) applyArrayValue(collection, path, value) → {Array}
- See:
-
- array.pick - to pick a row or column into an array
- array.applyArrayValues - applies an array safely and deeply onto another array of values
Applies deeply onto an array safely - in-place using dot-notation paths even if the child paths don't exist.
While tthis can be as simple as safely applying a value even if targetObj may be null
targetObj = [1, 2, null, 4, 5];
utils.object.applyPropertyValue(targetObj, '[2]', 3);
// [1, 2, 3, 4, 5]
// equivalent to targetObj[2] = 3;
This is much more safely working with deeply nested objects
targetObj = [{
name: 'john smith',
class: {
name: 'ECON_101',
professor: {
last_name: 'Winklemeyer'
}
}
}];
utils.object.applyPropertyValue(targetObj, '[0].class.professor.first_name', 'René');
// [{
// name: 'john smith',
// class: {
// name: 'ECON_101',
// professor: {
// last_name: 'Winklemeyer',
// first_name: 'René' // <- Added
// }
// }
// }];
or creating intermediary objects along the path - if they did not exist first.
targetObj = [{
name: 'john smith'
}];
utils.object.applyPropertyValue(targetObj, '[0].class.professor.first_name', 'René');
[{
name: 'john smith',
class: {
professor: {
first_name: 'René'
}
}
}];
Parameters:
Name | Type | Description |
---|---|---|
collection |
Array | array to apply the value to |
path |
string | dot notation path to set the value, ex: 'geo', or 'states[0].prop' |
value |
any | value to set |
Returns:
- the base array
- Type
- Array
(static) applyArrayValues(collection, path, value) → {Object}
- See:
-
- array.applyArrayValue - to apply a single value to a single object
- array.pick - to pick a row or column into an array
Converse from the extractPropertyValue, this takes a value / set of values and applies the values for each index in the collection.
for example:
weather = [{ id: 1, city: 'Seattle', month: 'Aug', precip: 0.87 },
{ id: 3, city: 'New York', month: 'Apr', precip: 3.94 },
{ id: 6, city: 'Chicago', month: 'Apr', precip: 3.62 }];
cities = utils.object.extractObjectProperty('city');
// ['Seattle', 'New York', 'Chicago'];
//-- async process to geocode
geocodedCities = geocodeCity(cities);
// [{ city: 'Seattle', state: 'WA', country: 'USA' },
// { city: 'New York', state: 'NY', country: 'USA' },
// { city: 'Chicago', state: 'IL', country: 'USA' }]
utils.applyArrayValues(weather, 'geo', geocodedCities);
// [{ id: 1, city: 'Seattle', month: 'Aug', precip: 0.87, geo: { city: 'Seattle', state: 'WA', country: 'USA' } },
// { id: 3, city: 'New York', month: 'Apr', precip: 3.94, geo: { city: 'New York', state: 'NY', country: 'USA' } },
// { id: 6, city: 'Chicago', month: 'Apr', precip: 3.62, geo: { city: 'Chicago', state: 'IL', country: 'USA' } }];
Note that traditional [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
works best for if you are working with objects completely in memory.
But this helps quite a bit if the action of mapping / transforming values
needs to be separate from the extraction / application of values back.
Parameters:
Name | Type | Description |
---|---|---|
collection |
Array | array to apply the value to on each index |
path |
string | dot notation path to set the value within each index, ex: 'geo', or 'states[0].prop' |
value |
any | the value that should be set at that path. |
Returns:
- Type
- Object
(static) arrange(length, startopt, stepopt) → {Array.<Number>}
- See:
-
- module:array.size for consistent values in the array
Creates an array of values to replace for loops
Example
utils.array.arange(10, 1)
.map((val) => `item ${val}`);
//
[
'item 1', 'item 2',
'item 3', 'item 4',
'item 5', 'item 6',
'item 7', 'item 8',
'item 9', 'item 10'
]
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
length |
Number | the number of items toreturn |
||
start |
Number |
<optional> |
0
|
the starting number |
step |
Number |
<optional> |
1
|
the number to increment for each step |
Returns:
- collection of numbers
- Type
- Array.<Number>
(static) arrangeMulti(…dimensions)
Creates an array for multiple dimensions of varying sizes.
(In order from higher order dimensions to lower)
utils.array.arangeMulti(0); // []
utils.array.arangeMulti(2); // [0, 1]
utils.array.arangeMulti(4); // [0, 1, 2, 3]
utils.array.arangeMulti(2, 2); // [[0, 1], [0, 1]]
utils.array.arangeMulti(2, 2, 2); // [[[0, 1], [0, 1]], [[0, 1], [0, 1]]]
utils.array.arangeMulti(2, 2, 4); // [[[0, 1, 2, 3], [0, 1, 2, 3]], [[0, 1, 2, 3], [0, 1, 2, 3]]]
Note that this can help with laying items out within a grid
gridPositions = utils.array.arangeMulti(4, 4)
.reduce((result, row, rowIndex) => [ ...result,
...row.reduce((rowReduce, value, columnIndex) => [...rowReduce, [rowIndex, columnIndex]], [])
], []);
// [
// [ 0, 0 ], [ 0, 1 ], [ 0, 2 ], [ 0, 3 ],
// [ 1, 0 ], [ 1, 1 ], [ 1, 2 ], [ 1, 3 ],
// [ 2, 0 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ],
// [ 3, 0 ], [ 3, 1 ], [ 3, 2 ], [ 3, 3 ]
// ]
myList.forEach((value, index) => {
const [x, y] = gridPositions[index];
console.log(`placing ${value} in row:${x}, column:${y}`);
});
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
dimensions |
any |
<repeatable> |
sizes of each dimension to create |
Returns:
Multi-dimensional array
(static) asyncWaitAndChain(seconds, fn, rows) → {Promise.<any>}
- See:
-
- chainFunctions - to execute methods right after each other.
- rxjs if you would like to execute more than one at a time.
Similar to chainFunctions - in that only one delayed function will occur at a time, but adds a delay between calls.
This also supports functions returning promises.
const sumValues = (...rest) => rest.reduce((result, val) => result + val, 0);
const arguments = [
[1],
[1, 1],
[1, 1, 2],
[1, 1, 2, 3]
];
utils.array.asyncWaitAndChain(3, sumValues, arguments)
.then((results) => console.log(`fibonnacci numbers: ${results}`));
// fibonacci numbers: [1, 2, 4, 7], but took 9 seconds to accomplish
Parameters:
Name | Type | Description |
---|---|---|
seconds |
Number | number of seconds to delay between each execution |
fn |
function | function to be called for each row of rows |
rows |
Array.<Array.<any>> | Array where each row are arguments to be applied to fn |
Returns:
- promise that will resolve when the last delayed function finishes
- Type
- Promise.<any>
(static) chainFunctions(fn, rows) → {Promise.<any>}
- See:
-
- rxjs if you would like to have more than one active at a time.
- asyncWaitAndChain - if you would like a delay between executions
Chain a set of functions to be called one after another (supports functions returning promises)
This is especially helpful if calls need to be rate limited to only having 1 occur at a time.
The resulting promise will return a list, with each entry corresponding with the row of arguments sent.
const sumValues = (...rest) => rest.reduce((result, val) => result + val, 0);
const arguments = [
[1],
[1, 1],
[1, 1, 2],
[1, 1, 2, 3]
];
utils.array.chainFunctions(sumValues, arguments)
.then((results) => console.log(`fibonnacci numbers: ${results}`));
// fibonacci numbers: [1, 2, 4, 7]
Parameters:
Name | Type | Description |
---|---|---|
fn |
function | the function to be called |
rows |
Array.<Array.<any>> | Array where each row are arguments to be applied to fn |
Returns:
- promise that will resolve when the last delayed function finishes
- Type
- Promise.<any>
(static) clone(target)
Deep clones multi-dimensional arrays.
If you want to just deep clone a 1d array, use [...target] instead
NOTE: this only deep clones Arrays, and not the values within the arrays.
const sourceArray = [[0, 1], [2, 3]];
const targetArray = utils.array.clone(sourceArray);
targetArray[0][0] = 99;
console.log(targetArray); // [[99, 1], [2, 3]];
console.log(sourceArray); // [[0, 1], [2, 3]];
Parameters:
Name | Type | Description |
---|---|---|
target |
any | Array | Array to be cloned |
Returns:
New deep-cloned array
(static) createSort(fieldName) → {function}
Creates a sort function based on fields of an object.
sampleData = [{score: 200, name: 'jane'}, {score: 200, name: 'john'}]
// sort by score descending, and then by name ascending
sampleData.sort(utils.array.createSort('-score','name'))
Example
sampleData = [{i:4}, {v:2}, {v:1}, {v:3}];
sortedData = sampleData.sort(
utils.createSort('-v')
);
// [{v:4}, {v:3}, {v:2}, {v:1}]
Parameters:
Name | Type | Description |
---|---|---|
fieldName |
String | name of property to sort by with - for descending |
Returns:
- Type
- function
(static) delayedFn(fn, …rest) → {function}
Defines a function and arguments that will only be called, only when the delayedFunction is called.
(Similar to Function.bind - but supports Function.call(1,2,3) or Function.apply([1,2,3]) syntax)
Example, these are equivalent, but the delayedFn does not mess with this
sayFn = (...rest) => console.log(...rest); arguments = [0, 1, 2, 3, 4, 5];
Spy(sayFn);
delayedFnA = sayFn.bind(globalThis, arguments); ... sayFn.calledCount; // 0 delayedFnA(); // consoles: [0, 1, 2, 3, 4, 5]; sayFn.calledCount; // 1
delayedFnB = utils.array.delayedFn(sayFn, 0, 1, 2, 3, 4, 5); ... delayedFnB(); // consoles: [0, 1, 2, 3, 4, 5];
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
fn |
function | Function to be executed at a later time |
|
rest |
any |
<repeatable> |
arguments to be passed to fn |
Returns:
- function that can be called to execute fn with the arguments
- Type
- function
(static) extractFromHardSpacedTable(str, columnWidths) → {Array.<Array.<String>>}
Useful for extracting out hard spaced string arrays separated by newlines
hardSpacedString = `
id first_name last_name city email gender ip_address airport_code car_model_year
-- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
3 Shawna Burghill London sburghill2@scribd.com Female 149.240.166.189 GBA 2004
4 Ginger Tween Lainqu gtween3@wordpress.com Female 132.67.225.203 EMS 1993
5 Elbertina Setford Los Angeles esetford4@ted.com Female 247.123.242.49 MEK 1989 `;
columns = [
'id ',
'first_name ',
'last_name ',
'city ',
'email ',
'gender ',
'ip_address ',
'airport_code ',
'car_model_year '
];
columnWidths = columns.map((str) => str.length);
// [ 3, 11, 11, 12, 29, 7, 16, 13, 15 ];
results = utils.array.extractFromHardSpacedTable(str, columnWidths);
[['id ', '-- ', '1 ', '2 ', '3 ', '4 ', '5 '],
['first_name ', '---------- ', 'Thekla ', 'Lexi ', 'Shawna ', 'Gin...', ...],
['last_name ', '---------- ', 'Brokenshaw ', 'Dugall ', 'Burghill ', 'Twe...', ...],
['city ', '----------- ', 'Chicago ', 'New York ', 'London ', ...],
['email ', '---------------------------- ', 'tbrokenshaw0...', ...],
['gender ', '------ ', 'Female ', 'Female ', 'Female ', 'Female ', 'Female '],
['ip_address ', '--------------- ', '81.118.170.238 ', '255.140.25.31 ', ...],
['airport_code ', '------------ ', 'CXI ', 'LBH ', 'GBA ...', ...],
['car_model_year', '--------------', '2003 ', '2005 ', '2004 ...', ...]]
We can then transpose the array to give us the format we might expect (non DataFrame centric)
resultsData = utils.array.transpose(results);
utils.table(resultsData).render();
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
id | first_name | last_name | city | gender | ip_address | airport_code | car_model_year | |
-- | ---------- | ---------- | ----------- | ---------------------------- | ------ | --------------- | ------------ | -------------- |
1 | Thekla | Brokenshaw | Chicago | tbrokenshaw0@kickstarter.com | Female | 81.118.170.238 | CXI | 2003 |
2 | Lexi | Dugall | New York | ldugall1@fc2.com | Female | 255.140.25.31 | LBH | 2005 |
3 | Shawna | Burghill | London | sburghill2@scribd.com | Female | 149.240.166.189 | GBA | 2004 |
4 | Ginger | Tween | Lainqu | gtween3@wordpress.com | Female | 132.67.225.203 | EMS | 1993 |
5 | Elbertina | Setford | Los Angeles | esetford4@ted.com | Female | 247.123.242.49 | MEK | 1989 |
Parameters:
Name | Type | Description |
---|---|---|
str |
String | Markdown / Hard Spaced Strings |
columnWidths |
Array.<Number> | Array of of the column widths to extract |
Returns:
- Array of Arrays, where each row is an extracted column
- Type
- Array.<Array.<String>>
(static) indexify(source, …sectionIndicatorFunctions) → {Array.<Object>}
Create a unique number index for each element in an array, alternatively using additional functions to indicate hierarchies of data.
For example, markdown can be considered a hierarchy of data:
markdownList = `# Overview
This entire list is a hierarchy of data.
# Section A
This describes section A
## SubSection 1
With a subsection belonging to Section A
## SubSection 2
And another subsection sibling to SubSection 1, but also under Section A.
# Section B
With an entirely unrelated section B, that is sibling to Section A
## SubSection 1
And another subsection 1, but this time related to Section B.`;
And we want to convert this 1d array into a hierarchy.
data = markdownList.split('\n')
.filter(line => line ? true : false); // check for empty lines
utils.format.consoleLines( data, 4);
// ['# Overview',
// 'This entire list is a hierarchy of data.',
// '# Section A',
// 'This describes section A',;
//-- functions that return True if we are in a new "group"
isHeader1 = (str) => str.startsWith('# ');
isHeader1('# Overview'); // true
isHeader1('This entire list is a hierarchy of data'); // false
isHeader1('# Section A'); // true
isHeader1('This describes section A'); // false
indexedData = utils.array.indexify(data, isHeader1);
[
{ entry: 'Heading', section: [ 0 ], subIndex: 1 },
{ entry: '# Overview', section: [ 1 ], subIndex: 0 },
{
entry: 'This entire list is a hierarchy of data.',
section: [ 1 ],
subIndex: 1
},
{ entry: '# Section A', section: [ 2 ], subIndex: 0 },
{ entry: 'This describes section A', section: [ 2 ], subIndex: 1 },
{ entry: '## SubSection 1', section: [ 2 ], subIndex: 2 },
{
entry: 'With a subsection belonging to Section A',
section: [ 2 ],
subIndex: 3
},
{ entry: '## SubSection 2', section: [ 2 ], subIndex: 4 },
{
entry: 'And another subsection sibling to SubSection 1, but also under Section A.',
section: [ 2 ],
subIndex: 5
},
{ entry: '# Section B', section: [ 3 ], subIndex: 0 },
{
entry: 'With an entirely unrelated section B, that is sibling to Section A',
section: [ 3 ],
subIndex: 1
},
{ entry: '## SubSection 1', section: [ 3 ], subIndex: 2 },
{
entry: 'And another subsection 1, but this time related to Section B.',
section: [ 3 ],
subIndex: 3
}
];
Note that this only indexes elements by the first header.
To index this with two levels of hierarchy, we can pass another function.
isHeader2 = (str) => str.startsWith('## ');
isHeader2('# Overview'); // false
isHeader2('This entire list is a hierarchy of data'); // false
isHeader2('# Section A'); // true
isHeader2('This describes section A'); // false
indexedData = utils.array.indexify(data, isHeader1, isHeader2);
// [
// { entry: 'Heading', section: [ 0, 0 ], subIndex: 1 },
// { entry: '# Overview', section: [ 1, 0 ], subIndex: 0 },
// {
// entry: 'This entire list is a hierarchy of data.',
// section: [ 1, 0 ],
// subIndex: 1
// },
// { entry: '# Section A', section: [ 2, 0 ], subIndex: 0 },
// { entry: 'This describes section A', section: [ 2, 0 ], subIndex: 1 },
// { entry: '## SubSection 1', section: [ 2, 1 ], subIndex: 0 },
// {
// entry: 'With a subsection belonging to Section A',
// section: [ 2, 1 ],
// subIndex: 1
// },
// { entry: '## SubSection 2', section: [ 2, 2 ], subIndex: 0 },
// {
// entry: 'And another subsection sibling to SubSection 1, but also under Section A.',
// section: [ 2, 2 ],
// subIndex: 1
// },
// { entry: '# Section B', section: [ 3, 0 ], subIndex: 0 },
// {
// entry: 'With an entirely unrelated section B, that is sibling to Section A',
// section: [ 3, 0 ],
// subIndex: 1
// },
// { entry: '## SubSection 1', section: [ 3, 1 ], subIndex: 0 },
// {
// entry: 'And another subsection 1, but this time related to Section B.',
// section: [ 3, 1 ],
// subIndex: 1
// }
// ];
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
source |
Array | list of values to index |
|
sectionIndicatorFunctions |
function |
<repeatable> |
each function indicates a new section |
Returns:
- collection of objects, each with a new section (indicating the layers) and subIndex: unique value in the section (always 0 for header)
- Type
- Array.<Object>
(static) isMultiDimensional(targetArray) → {Boolean}
Determine whether an array is multi-dimensional (an array of arrays)
For example:
utils.array.isMultiDimensional(0); // false
utils.array.isMultiDimensional([0,1,2,3]); // false
utils.array.isMultiDimensional([[0,1], [2,3]]); // true
utils.array.isMultiDimensional([0, [1,2]]); // true
Parameters:
Name | Type | Description |
---|---|---|
targetArray |
Array | array to check if multi-dimensional |
Returns:
- if the targetArray has any values that are multi-dimensional
- Type
- Boolean
(static) multiLineSubstr(str, start, lenopt) → {Array.<String>}
- See:
-
- multiLineSubstring - to use start and end character positions
- multiStepReduce - for example on how to extract data from hard spaced arrays array.size(size, default) - generate array of a specific size and CONSISTENT default value
Parse a fixed length table of strings (often in markdown format)
This is different from multiLineSubString in this uses a start position and string length (not start and end position per line)
For example, say you got a string formatted like this:
hardSpacedString = `
id first_name last_name city email gender ip_address airport_code car_model_year
-- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
3 Shawna Burghill London sburghill2@scribd.com Female 149.240.166.189 GBA 2004
4 Ginger Tween Lainqu gtween3@wordpress.com Female 132.67.225.203 EMS 1993
5 Elbertina Setford Los Angeles esetford4@ted.com Female 247.123.242.49 MEK 1989 `;
This can be a bit hard to parse, because the space delimiter is a valid character in the city
column, ex: New York
.
Instead, we can use the starting index and number of characters, to extract the data out
const carModelYears = ArrayUtils.multiLineSubstr(hardSpacedString, 102);
// ['car_model_year', '--------------', '2003 ', '2005 ', '2004 ', '1993 ', '1989'];
const ipAddresses = ArrayUtils.multiLineSubstr(hardSpacedString, 73, 14);
// ['ip_address ', '--------------', '81.118.170.238', '255.140.25.31 ', '149.240.166.18', '132.67.225.203', '247.123.242.49'];
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
str |
String | Array.<String> | multi-line string or array of strings |
||
start |
Number | the starting index to substr |
||
len |
Number |
<optional> |
0
|
optional length of string to substr |
Returns:
- substr values from each line
- Type
- Array.<String>
(static) multiLineSubstring(str, startPosition, endPositionopt) → {Array.<String>}
- See:
-
- multiLineSubstr - to use character start and length
- multiStepReduce - for example on how to extract data from hard spaced arrays
Parse a fixed length table of strings (often in markdown format)
This is different from multiLineSubStr in this uses a start and end position (not start and length)
For example, say you got a string formatted like this:
hardSpacedString = `
id first_name last_name city email gender ip_address airport_code car_model_year
-- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
3 Shawna Burghill London sburghill2@scribd.com Female 149.240.166.189 GBA 2004
4 Ginger Tween Lainqu gtween3@wordpress.com Female 132.67.225.203 EMS 1993
5 Elbertina Setford Los Angeles esetford4@ted.com Female 247.123.242.49 MEK 1989 `;
This can be a bit hard to parse, because the space delimiter is a valid character in the city
column, ex: New York
.
Instead, we can use the starting index and number of characters, to extract the data out.
Note, this function uses the starting and ending character positions, to extract, where multiLineSubstr - uses the start and character length instead.
const carModelYears = ArrayUtils.multiLineSubstring(hardSpacedString, 102);
// ['car_model_year', '--------------', '2003 ', '2005 ', '2004 ', '1993 ', '1989'];
const ipAddresses = ArrayUtils.multiLineSubstring(hardSpacedString, 73, 87);
// ['ip_address ', '--------------', '81.118.170.238', '255.140.25.31 ', '149.240.166.18', '132.67.225.203', '247.123.242.49'];
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
str |
String | Array.<String> | multi-line string or array of strings |
|
startPosition |
Number | the starting index to extract out - using the standard |
|
endPosition |
Number |
<optional> |
the ending endex to extract out |
Returns:
- substr values from each line
- Type
- Array.<String>
(static) multiStepReduce()
Returns the reduce at each step along the way.
For example, if you have a set of column widths and would like to know how wide the table is after each column.
For example:
hardSpacedString = `
id first_name last_name city email gender ip_address airport_code car_model_year
-- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
3 Shawna Burghill London sburghill2@scribd.com Female 149.240.166.189 GBA 2004
4 Ginger Tween Lainqu gtween3@wordpress.com Female 132.67.225.203 EMS 1993
5 Elbertina Setford Los Angeles esetford4@ted.com Female 247.123.242.49 MEK 1989 `;
columns = [
'id ',
'first_name ',
'last_name ',
'city ',
'email ',
'gender ',
'ip_address ',
'airport_code ',
'car_model_year '
];
columnWidths = columns.map((str) => str.length);
// [ 3, 11, 11, 12, 29, 7, 16, 13, 15 ];
//-- get the starting position for each column,
//-- ex: column 3 is sum of columnWidths[0..3] or 0 + 3 + 11 + 11 or 25
columnStops = utils.array.multiStepReduce( columnWidths, (a,b) => a + b, 0);
// [0, 3, 14, 25, 37, 66, 73, 89, 102, 117];
We can then pair with the column widths - to get exactly the starting position and width of each column.
substrPairs = columnWidths.map((value, index) => [columnStops[index], value]);
// [[0, 3], [3, 11], [14, 11], [25, 12], [37, 29], [66, 7], [73, 16], [89, 13], [102, 15]];
Now that we know how the starting positions for each of the columns, we can try picking one column out:
//-- we can get a single column like this:
cityStartingCharacter = substrPairs[3][0]; // 25
cityColumnLength = substrPairs[3][1]; // 12
cityData = ArrayUtils.multiLineSubstr(hardSpacedString, cityStartingCharacter, cityColumnLength);
// ['city ', '----------- ', 'Chicago ', 'New York ', 'London ', 'Lainqu ', 'Los Angeles ']
Or we can get all columns with something like this:
results = substrPairs.map(
([startingPos, length]) => ArrayUtils.multiLineSubstr(hardSpacedString, startingPos, length)
);
[['id ', '-- ', '1 ', '2 ', '3 ', '4 ', '5 '],
['first_name ', '---------- ', 'Thekla ', 'Lexi ', 'Shawna ', 'Gin...', ...],
['last_name ', '---------- ', 'Brokenshaw ', 'Dugall ', 'Burghill ', 'Twe...', ...],
['city ', '----------- ', 'Chicago ', 'New York ', 'London ', ...],
['email ', '---------------------------- ', 'tbrokenshaw0...', ...],
['gender ', '------ ', 'Female ', 'Female ', 'Female ', 'Female ', 'Female '],
['ip_address ', '--------------- ', '81.118.170.238 ', '255.140.25.31 ', ...],
['airport_code ', '------------ ', 'CXI ', 'LBH ', 'GBA ...', ...],
['car_model_year', '--------------', '2003 ', '2005 ', '2004 ...', ...]]
We can then transpose the array to give us the format we might expect (non DataFrame centric)
resultsData = utils.array.transpose(results);
utils.table(resultsData).render();
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
id | first_name | last_name | city | gender | ip_address | airport_code | car_model_year | |
-- | ---------- | ---------- | ----------- | ---------------------------- | ------ | --------------- | ------------ | -------------- |
1 | Thekla | Brokenshaw | Chicago | tbrokenshaw0@kickstarter.com | Female | 81.118.170.238 | CXI | 2003 |
2 | Lexi | Dugall | New York | ldugall1@fc2.com | Female | 255.140.25.31 | LBH | 2005 |
3 | Shawna | Burghill | London | sburghill2@scribd.com | Female | 149.240.166.189 | GBA | 2004 |
4 | Ginger | Tween | Lainqu | gtween3@wordpress.com | Female | 132.67.225.203 | EMS | 1993 |
5 | Elbertina | Setford | Los Angeles | esetford4@ted.com | Female | 247.123.242.49 | MEK | 1989 |
This can also be helpful with coming up with complex array.arrange(size, start, step) collections.
(static) peekFirst(targetArray, defaultVal) → {any}
Peek in an array and return the first value in the array.
Or return the default value (defaultVal
) - if the array is empty
Parameters:
Name | Type | Description |
---|---|---|
targetArray |
Array | array to be peeked within |
defaultVal |
any | the value to return if the array is empty |
Returns:
- Type
- any
(static) peekLast(targetArray, defaultVal) → {any}
Peek in an array and return the last value in the array.
Or return the default value (defaultVal
) - if the array is empty
Parameters:
Name | Type | Description |
---|---|---|
targetArray |
Array | array to be peeked within |
defaultVal |
any | the value to return if the array is empty |
Returns:
- Type
- any
(static) pick(array2d, options) → {Array}
- See:
-
- array.pickRows - picking rows
- array.pickColumns - picking columns
- array.applyArrayValues - applies a value / multiple values deeply into an array safely
Convenience function for picking specific rows and columns from a 2d array.
Please also see Danfo.js for working with DataFrames.
Example
data = [
['john', 23, 'purple'],
['jane', 32, 'red'],
['ringo', 27, 'green']
];
utils.array.pick(data, {rows: [0, 1]});
//-- [['john', 23, 'purple'], ['jane', 32, 'red']];
utils.array.pick(data, {columns: [0, 2]});
//-- [['john', 'purple'], ['jane', 'red'], ['ringo', 'green']];
utils.array.pick(data, {rows:[0, 1], columns:[0, 2]});
//-- [['john', 'purple'], ['jane', 'red']];
Parameters:
Name | Type | Description | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
array2d |
Array | 2d array to pick from [row][column] |
|||||||||||||||
options |
Object | options on which to pick Properties
|
Returns:
-
- 2d array of only the rows and columns chosen.
- Type
- Array
-
- 2dArray of the columns and rows requested
(static) pickColumns(array2d, …columns)
- See:
-
- array.pick - pick either rows or columns
Picks a column (or multiple columns) from a 2d array
Please also see Danfo.js for working with DataFrames.
Example
data = [
['john', 23, 'purple'],
['jane', 32, 'red'],
['ringo', 27, 'green']
];
utils.array.pickColumns(data, 0);
//-- [['john'], ['jane'], ['ringo']];
utils.array.pickColumns(data, 0, 2);
//-- [['john', 'purple'], ['jane', 'red'], ['ringo', 'green']];
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
array2d |
Array | 2d array to pick from [row][column] |
|
columns |
any |
<repeatable> |
Indexes of the columns to pick the values from: [0...row.length-1] |
Returns:
- Array with all rows, and only those columns
(static) pickRows(array2d, …rowIndices)
- See:
-
- array.pick - pick either rows or columns
Picks a row (or multiple rows) from a 2d array.
Please also see Danfo.js for working with DataFrames.
Example
data = [
['john', 23, 'purple'],
['jane', 32, 'red'],
['ringo', 27, 'green']
];
utils.array.pickRows(data, 0);
//-- [['john', 23, 'purple']];
utils.array.pickRows(data, 0, 1);
//-- [['john', 23, 'purple'], ['jane', 32, 'red']];
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
array2d |
Array | 2d array to pick from [row][column] |
|
rowIndices |
Number |
<repeatable> |
Indexes of the row to return, [0...length-1] |
Returns:
- Array with only those rows
(static) reshape(sourceArray, numColumns) → {Array.<Array.<any>>}
Resizes an NxM dimensional array by number of columns
Example
baseArray = utils.array.arrange(12);
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
]
//-- resize the 1d array based on 3 columns
newArray = utils.array.reshape(baseArray, 3)
[ [ 0, 1, 2 ],
[ 3, 4, 5 ],
[ 6, 7, 8 ],
[ 9, 10, 11 ] ];
//-- now resize the 4x3 array to 3x4
utils.array.reshape(newArray, 4);
[ [ 0, 1, 2, 3 ],
[ 4, 5, 6, 7 ],
[ 8, 9, 10, 11 ] ]
Parameters:
Name | Type | Description |
---|---|---|
sourceArray |
Array.<any> | an array to resize |
numColumns |
Number | number of columns |
Returns:
- 2 dimensinal array
- Type
- Array.<Array.<any>>
(static) size(length, defaultValue) → {Array}
- See:
Creates an array of a specific size and default value
Especially useful for forLoops, map or reduce
Example
utils.array.size(3, null)
.map((v, index) => `item ${index}`)
Parameters:
Name | Type | Description |
---|---|---|
length |
Number | the length of the new array |
defaultValue |
any | the new value to put in each cell |
Returns:
- an array of length size with default values
- Type
- Array
(static) transpose(matrix) → {Array.<any>}
Transposes a two dimensional array, so an NxM becomes MxN
Example
baseArray = [ 0, 1, 2, 3, 4 ];
utils.array.transpose(utils.array.arrange(5))
//
[ [ 0 ],
[ 1 ],
[ 2 ],
[ 3 ],
[ 4 ] ]
Parameters:
Name | Type | Description |
---|---|---|
matrix |
Array.<any> | MxN array |
Returns:
- NxM array
- Type
- Array.<any>