Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dodos

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dodos - npm Package Compare versions

Comparing version 1.9.0 to 2.0.0

.nyc_output/51458.json

11

package.json
{
"name": "dodos",
"version": "1.9.0",
"version": "2.0.0",
"description": "Pandas-inspired iterator-based data wrangling library for js",

@@ -33,11 +33,16 @@ "main": "dist/dodos.js",

"babel-require": "~1.0.1",
"benchmark": "~2.1.0",
"console-table": "~0.1.2",
"d3-dsv": "~0.3.1",
"eslint": "~2.4.0",
"husky": "~0.11.4",
"lodash": "~4.6.1",
"npm-check": "~4.1.4",
"nyc": "~6.1.1",
"table": "~3.7.8",
"webpack": "~1.12.14"
},
"dependencies": {
"invariant": "~2.2.1"
"invariant": "~2.2.1",
"lodash": "~4.6.1",
"transducers.js": "~0.3.2"
},

@@ -44,0 +49,0 @@ "babel": {

@@ -6,5 +6,3 @@ import invariant from 'invariant'

const MAP_ACTION = 'MAP_ACTION'
const FILTER_ACTION = 'FILTER_ACTION'
const SLICE_ACTION = 'SLICE_ACTION'
import {map, filter, drop, take, seq, compose} from 'transducers.js'

@@ -21,10 +19,20 @@ const action = Symbol('action')

const isfunc = fn => fn && typeof fn == 'function'
const arrayToIndex = arr => zipObject(arr, [...arr.keys()])
export default class Dodo {
constructor(array, actions=noActions) {
invariant(array, `new Dodo(array) - array is required`)
constructor(array, index, actions=noActions) {
if (Array.isArray(index))
index = arrayToIndex(index)
invariant(Array.isArray(array), `new Dodo(arr, index) - arr is required`)
invariant(index && Object.keys(index).length == array[0].length,
`new Dodo(arr, index) - index is missing or malformed`)
Arrays.set(this, array)
if (!ArraysMetadata.has(array))
ArraysMetadata.set(array, {
index: index,
length: array.length,
columns: new Set(Object.keys(array.index)),
columns: new Set(Object.keys(index)),
})

@@ -37,5 +45,3 @@ this.actions = actions

get [index]() {
const lastMapWithIndex = this.actions
.filter(act => act.type == MAP_ACTION && act.I)
.slice(-1)
const lastMapWithIndex = this.actions.filter(act => !!act.I).slice(-1)

@@ -45,3 +51,3 @@ if (lastMapWithIndex.length)

else
return Arrays.get(this).index
return this[meta].index
}

@@ -54,89 +60,47 @@

[action](action) {
return new Dodo(Arrays.get(this), [...this.actions, action])
[Symbol.iterator]() { return this.toArray().values() }
toArray() {
if (this.actions.length)
return seq(Arrays.get(this), compose(...this.actions))
else
return Arrays.get(this)
}
*[Symbol.iterator]() {
const array = Arrays.get(this)
const Index = array.index
const nrOfActions = this.actions.length
uniq() { return [...new Set(this)] }
if (!nrOfActions) {
yield* array
} else {
const lastActionIndex = this.actions.length - 1
let lastRowIndex = ArraysMetadata.get(array).length - 1
let rowIndex
const firstNonMap = this.actions
.filter(act => act.type != MAP_ACTION)
.slice(0, 1)
if (firstNonMap.type == SLICE_ACTION)
rowIndex = firstNonMap.start - 1
else
rowIndex = -1
while (rowIndex++ < lastRowIndex) {
let row = array[rowIndex]
let actionIndex = -1
let I = Index
while (actionIndex++ < lastActionIndex) {
const action = this.actions[actionIndex]
if (action.type == SLICE_ACTION) {
if (++action.counter < action.first)
break
if (action.counter == action.last)
lastRowIndex = rowIndex
} if (action.type == FILTER_ACTION) {
if (!action(row, I))
break
} if (action.type == MAP_ACTION) {
row = action(row, I)
I = action.I || I
}
if (actionIndex == lastActionIndex)
yield row
}
}
}
[action](action) {
return new Dodo(
Arrays.get(this), this[meta].index, [...this.actions, action])
}
toArray() { return [...this] }
uniq() { return [...new Set(this)] }
filter(fn) {
invariant(fn && typeof fn == 'function',
`Dodo#filter(fn) — fn not a function`)
fn.type = FILTER_ACTION
return this[action](fn)
invariant(isfunc(fn), `Dodo#filter(fn) — fn not a function`)
const I = this[index]
return this[action](filter(row => fn(row, I)))
}
filterBy(col, fn) {
invariant(col, `Dodo#filterBy(col, fn) - col is required`)
invariant(fn, `Dodo#filterBy(col, fn) - fn is required`)
return this.filter( (row, I) => fn(row[I[col]]) )
filterBy(name, fn) {
invariant(name, `Dodo#filterBy(name, fn) - col is required`)
invariant(isfunc(fn), `Dodo#filterBy(name, fn) - fn not a function`)
const col = this[index][name]
return this[action]( filter(row => fn(row[col])) )
}
map(fn) {
invariant(fn && typeof fn == 'function', `Dodo#map(fn) — fn not a function`)
fn.type = MAP_ACTION
return this[action](fn)
invariant(isfunc(fn), `Dodo#map(fn) — fn not a function`)
const I = this[index]
return this[action](map(row => fn(row, I)))
}
col(name) {
invariant(name, `Dodo#col(name) - name is required`)
invariant(name, `Dodo#filterBy(name, fn) - col is required`)
invariant(this[meta].columns.has(name),
`Dodo#col(name) — name ${name} not in index`)
const col = this[index][name]
return this.map(row => row[col])
return this[action](map(row => row[col]))
}
cols(names) {
invariant(names, `Dodo#cols(names) - names is required`)
invariant(Array.isArray(names), `Dodo#cols(names) - names is required`)
names.forEach(name => invariant(

@@ -146,28 +110,12 @@ this[meta].columns.has(name),

))
const fn = (row, I) => names.map(name => row[I[name]])
fn.I = zipObject(names, [...names.keys()])
return this.map(fn)
const indices = names.map(name => this[index][name])
const fn = map(row => indices.map(i => row[i]))
fn.I = arrayToIndex(names)
return this[action](fn)
}
slice(start=0, end) {
const len = this[meta].length
if (typeof end != 'number')
end = len
if (end == len && start == 0)
return this
invariant(start >= 0, `Dodo#slice(start, end) — start smaller than 0`)
invariant(end >= 0, `Dodo#slice(start, end) — end smaller than 0`)
invariant(start < end, `Dodo#slice(start, end) — end larger than start`)
return this[action]({
type: SLICE_ACTION,
counter: -1,
first: start,
last: end - 1,
})
}
skip(amount) {
invariant(amount, `Dodo#skip(amount) - amount is required`)
invariant(amount > 0, `Dodo#skip(amount) — amount smaller than 0`)
return this.slice(amount)
return this[action](drop(amount))
}

@@ -178,7 +126,7 @@

invariant(amount > 0, `Dodo#take(amount) — amount smaller than 0`)
return this.slice(0, amount)
return this[action](take(amount))
}
[dispatchReduce](args) {
if (this[index] == Arrays.get(this).index)
if (this[index] == this[meta].index)
return this.reduce(...args())

@@ -191,6 +139,11 @@ else

invariant(init != null, `Dodo#reduce(fn, init, final) - init is required`)
invariant(fn && typeof fn == 'function',
`Dodo#reduce(fn, init, final) — fn not a function`)
for (const row of this)
init = fn(init, row)
invariant(isfunc(fn), `Dodo#reduce(fn, init, final) — fn not a function`)
invariant(isfunc(final),
`Dodo#reduce(fn, init, final) — final not a function`)
const array = this.toArray()
const len = array.length
let i = -1
while (++i < len) {
init = fn(init, array[i])
}
return final === identity ? init : final(init)

@@ -239,2 +192,4 @@ }

Dodo.prototype.drop = Dodo.prototype.skip
const spread = (fns) => {

@@ -307,4 +262,3 @@ const len = fns.length

return function(array, key, map) {
array.index = Index
map.set(key, new Dodo(array))
map.set(key, new Dodo(array, Index))
}

@@ -311,0 +265,0 @@ }

@@ -5,8 +5,7 @@ import test from 'ava'

import Dodo from '../src/dodo'
import table from './fixtures/table'
const array = [...table]
const Index = table.index
import {table, index} from '../fixtures/table'
const array = table
test('no actions', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.ok(dodo.actions.length === 0)

@@ -16,33 +15,19 @@ t.same([...dodo], array)

test('throws without an array', t => {
t.throws(() => new Dodo())
})
test('slice', t => {
const dodo = new Dodo(table)
test('accepts index as array', t => {
const dodo = new Dodo(table, Object.keys(index))
t.same(
[...dodo.slice(0, 2)],
array.slice(0, 2)
dodo.filterBy('Date', d => d == 4).toArray(),
array.filter(row => row[index.Date] == 4)
)
t.same(
[...dodo.slice(1, 2)],
array.slice(1, 2)
)
t.same(
[...dodo.slice(0, array.length)],
array
)
t.same(
[...dodo.slice(0)],
array
)
t.same(
[...dodo.slice()],
array
)
t.throws(dodo.slice.bind(dodo, 2, 2))
})
test('throws without an array or index', t => {
t.throws(() => new Dodo())
t.throws(() => new Dodo(table))
t.throws(() => new Dodo({notAn: 'array'}))
t.throws(() => new Dodo(table, {abc: 0}))
})
test('slice shorthand: take', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(

@@ -55,3 +40,3 @@ dodo.take(10).toArray(),

test('slice shorthand: skip', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(

@@ -63,44 +48,15 @@ dodo.skip(3).toArray(),

test('slice + slice', t => {
const dodo = new Dodo(table)
t.same(
[...dodo.slice(0, 2).skip(2)],
array.slice(0, 2).slice(2)
)
t.same(
[...dodo.slice(1, 2).slice(0)],
array.slice(1, 2)
)
t.same(
[...dodo.slice(0, 2).slice(1, 2)],
array.slice(0, 2).slice(1, 2)
)
t.same(
[...dodo.slice(0, 2).take(3)],
array.slice(0, 2).slice(0, 3)
)
t.same(
[...dodo.slice(0, 5).slice(0, 2)],
array.slice(0, 2)
)
t.same(
[...dodo.slice(1).slice(0, 2)],
array.slice(1).slice(0, 2)
)
t.throws(dodo.slice(2).slice.bind(dodo, 2, 2))
})
test('filter', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
dodo.filter((row, I) => row[I.Date] == 4).toArray(),
array.filter(row => row[Index.Date] == 4)
array.filter(row => row[index.Date] == 4)
)
t.same(
dodo.filter((row, I) => row[I.Date] <= 4).toArray(),
array.filter(row => row[Index.Date] <= 4)
array.filter(row => row[index.Date] <= 4)
)
t.same(
dodo.filter((row, I) => row[I.Age] <= 4 && row[I.Weight] == 2).toArray(),
array.filter(row => row[Index.Age] <= 4 && row[Index.Weight] == 2)
array.filter(row => row[index.Age] <= 4 && row[index.Weight] == 2)
)

@@ -112,10 +68,10 @@ t.throws(() => dodo.filter())

test('filter shorthand: filterBy', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
dodo.filterBy('Date', d => d == 4).toArray(),
array.filter(row => row[Index.Date] == 4)
array.filter(row => row[index.Date] == 4)
)
t.same(
dodo.filterBy('Age', a => a <= 4).toArray(),
array.filter(row => row[Index.Age] <= 4)
array.filter(row => row[index.Age] <= 4)
)

@@ -125,6 +81,6 @@ })

test('filter + filter', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const expected = array
.filter(row => row[Index.Date] == 4)
.filter(r => r[Index.Weight] == 2)
.filter(row => row[index.Date] == 4)
.filter(r => r[index.Weight] == 2)

@@ -145,14 +101,14 @@ t.same(

test('map', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
dodo.map((row, I) => row[I.Date]).toArray(),
array.map(row => row[Index.Date])
array.map(row => row[index.Date])
)
t.same(
dodo.map((row, I) => row[I.Date] * 2).toArray(),
array.map(row => row[Index.Date] * 2)
array.map(row => row[index.Date] * 2)
)
t.same(
dodo.map((row, I) => row[I.Date] + row[I.Age]).toArray(),
array.map(row => row[Index.Date] + row[Index.Age])
array.map(row => row[index.Date] + row[index.Age])
)

@@ -164,6 +120,6 @@ t.throws(() => dodo.map())

test('map shorthand: col', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
dodo.col('Date').toArray(),
array.map(row => row[Index.Date])
array.map(row => row[index.Date])
)

@@ -175,7 +131,7 @@ t.throws(() => dodo.col('some column not in the index'))

test('map shorthand: cols', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const cols = ['Date', 'Age', 'Height']
t.same(
dodo.cols(cols).toArray(),
array.map(row => cols.map(col => row[Index[col]]))
array.map(row => cols.map(col => row[index[col]]))
)

@@ -186,6 +142,6 @@ t.throws(() => dodo.cols([...cols, 'Column that does not exist']))

test('multiple maps', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
dodo.col('Date').map(d => d * 2).toArray(),
array.map(row => row[Index.Date]).map(d => d * 2)
array.map(row => row[index.Date]).map(d => d * 2)
)

@@ -195,3 +151,3 @@ const cols = ['Age', 'Date', 'Height', 'Weight']

[...dodo.cols(cols).col('Date')],
array.map(row => row[Index.Date])
array.map(row => row[index.Date])
)

@@ -201,3 +157,3 @@ const colsAfter = ['Age', 'Date']

[...dodo.cols(cols).cols(colsAfter)],
array.map(row => colsAfter.map(col => row[Index[col]]))
array.map(row => colsAfter.map(col => row[index[col]]))
)

@@ -207,9 +163,9 @@ })

test('map + filter', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const expected = array
.filter(row => row[Index.Date] > 3)
.map(row => row[Index.Date])
.filter(row => row[index.Date] > 3)
.map(row => row[index.Date])
t.same(
dodo.filter((row, I) => row[I.Date] > 3).col('Date').toArray(),
dodo.filterBy('Date', d => d > 3).col('Date').toArray(),
expected

@@ -228,3 +184,3 @@ )

array
.map(row => row[Index.Date])
.map(row => row[index.Date])
.filter(a => a > 3)

@@ -240,3 +196,3 @@ .map(a => a * 2)

array
.map(row => cols.map(col => row[Index[col]]))
.map(row => cols.map(col => row[index[col]]))
.filter(row => row[1] == 7)

@@ -251,4 +207,4 @@ )

array
.filter(row => row[Index.Height] == 7)
.map(row => cols.map(col => row[Index[col]]))
.filter(row => row[index.Height] == 7)
.map(row => cols.map(col => row[index[col]]))
.filter(row => row[cols.indexOf('Age')] == 5)

@@ -260,10 +216,10 @@ .map(row => row[cols.indexOf('Date')])

test('map + slice', t => {
const dodo = new Dodo(table)
const expected = array.map(row => row[Index.Date] * 2).slice(2, 4)
const dodo = new Dodo(table, index)
const expected = array.map(row => row[index.Date] * 2).slice(2, 4)
t.same(
dodo.map((row, I) => row[I.Date] * 2).slice(2, 4).toArray(),
dodo.map((row, I) => row[I.Date] * 2).drop(2).take(2).toArray(),
expected
)
t.same(
dodo.slice(2, 4).map((row, I) => row[I.Date] * 2).toArray(),
dodo.drop(2).take(2).map((row, I) => row[I.Date] * 2).toArray(),
expected

@@ -274,10 +230,10 @@ )

test('filter + slice', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
[...dodo.filter((row, I) => row[I.Date] == 4).slice(1)],
array.filter(row => row[Index.Date] == 4).slice(1)
[...dodo.filter((row, I) => row[I.Date] == 4).skip(1)],
array.filter(row => row[index.Date] == 4).slice(1)
)
t.same(
[...dodo.slice(1).filter((row, I) => row[I.Date] == 4)],
array.slice(1).filter(row => row[Index.Date] == 4)
[...dodo.skip(1).filter((row, I) => row[I.Date] == 4)],
array.slice(1).filter(row => row[index.Date] == 4)
)

@@ -287,17 +243,15 @@ t.same(

.filter((row, I) => row[I.Date] >= 4)
.slice(1)
.skip(1)
.filter((row, I) => row[I.Height] == 7)
.slice(0)
.toArray(),
array
.filter(row => row[Index.Date] >= 4)
.filter(row => row[index.Date] >= 4)
.slice(1)
.filter(row => row[Index.Height] == 7)
.slice(0)
.filter(row => row[index.Height] == 7)
)
t.same(
dodo
.slice(1)
.skip(1)
.filter((row, I) => row[I.Date] >= 4)
.slice(1)
.skip(1)
.filter((row, I) => row[I.Height] == 7)

@@ -307,5 +261,5 @@ .toArray(),

.slice(1)
.filter(row => row[Index.Date] >= 4)
.filter(row => row[index.Date] >= 4)
.slice(1)
.filter(row => row[Index.Height] == 7)
.filter(row => row[index.Height] == 7)
)

@@ -315,7 +269,7 @@ })

test('uniq', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.true(Array.isArray(dodo.col('Date').uniq()))
t.same(
dodo.col('Date').uniq(),
[...new Set(array.map(row => row[Index.Date]))]
[...new Set(array.map(row => row[index.Date]))]
)

@@ -325,6 +279,6 @@ })

test('reduce of single column', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
t.same(
dodo.col('Age').reduce((acc, a) => acc * a, 1),
array.map(row => row[Index.Age]).reduce((acc, a) => acc * a, 1)
array.map(row => row[index.Age]).reduce((acc, a) => acc * a, 1)
)

@@ -334,4 +288,4 @@ })

test.skip('reduce over multiple columns', t => {
const dodo = new Dodo(table)
const cols = Object.keys(Index)
const dodo = new Dodo(table, index)
const cols = Object.keys(index)
t.same(

@@ -341,3 +295,3 @@ dodo.reduceEach((acc, a) => acc + a, 0),

cols,
Object.values(Index)
Object.values(index)
.map(i => array.reduce((arr, row) => [...arr, row[i]], []))

@@ -350,3 +304,3 @@ .map(arr => arr.reduce((acc, a) => acc + a, 0))

test('reduce shorthands', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const shorthands = [

@@ -365,3 +319,3 @@ ['count', arr => arr.length],

dodo.col(col)[s[0]](),
s[1](array.map(row => row[Index.Date])),
s[1](array.map(row => row[index.Date])),
`${s[0]} over 1 column`

@@ -373,3 +327,3 @@ )

cols,
cols.map(col => array.map(row => row[Index[col]])).map(col => s[1](col))
cols.map(col => array.map(row => row[index[col]])).map(col => s[1](col))
),

@@ -404,3 +358,3 @@ `${s[0]} over several columns`

test('groupBy without key function', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const grouped = dodo.groupBy('Age')

@@ -417,3 +371,3 @@ const ageUniques = dodo.col('Age').uniq()

test('groupBy with key function', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const mapper = age => Math.ceil(age / 3)

@@ -431,3 +385,3 @@ const grouped = dodo.groupBy('Age', mapper)

test('groupBy(): Dodo prototype methods present', t => {
const grouped = new Dodo(table).groupBy('Age')
const grouped = new Dodo(table, index).groupBy('Age')
const methods = new Set(Object.getOwnPropertyNames(grouped))

@@ -442,3 +396,3 @@ for (const method of Object.getOwnPropertyNames(Dodo.prototype)) {

test('groupBy().map()', t => {
const dodo = new Dodo(table)
const dodo = new Dodo(table, index)
const grouped = dodo.groupBy('Age')

@@ -465,3 +419,3 @@ const ageUniques = dodo.col('Age').uniq()

test('groupBy(): Dodo prototype methods absent after toArray', t => {
const grouped = new Dodo(table).groupBy('Age')
const grouped = new Dodo(table, index).groupBy('Age')
const groupedToArray = grouped.toArray()

@@ -476,3 +430,3 @@ const methods = new Set(Object.getOwnPropertyNames(groupedToArray))

test('groupBy().mapEntries()', t => {
const grouped = new Dodo(table).groupBy('Age')
const grouped = new Dodo(table, index).groupBy('Age')
const expected = []

@@ -479,0 +433,0 @@ const mapper = (dodo, value) => dodo.toArray() + value

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc