Socket
Socket
Sign inDemoInstall

map-filter-reduce

Package Overview
Dependencies
1
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.0 to 1.0.0

index.js

7

filter.js
var u = require('./util')
var isExact = u.isExact
var isBasic = u.isBasic
var isRange = u.isRange

@@ -11,2 +11,3 @@ var isString = u.isString

function exact(q) {
console.log('Exact', q)
return function (v) {

@@ -66,4 +67,5 @@ return q === v

function make (q) {
console.log('Make', q)
return (
isExact(q) ? exact(q)
isBasic(q) ? exact(q)
: has(q, '$prefix') ? prefix(q.$prefix)

@@ -82,1 +84,2 @@ : isLtgt(q) ? ltgt(q)

{
"name": "map-filter-reduce",
"description": "",
"version": "0.0.0",
"version": "1.0.0",
"homepage": "https://github.com/dominictarr/map-filter-reduce",

@@ -10,3 +10,5 @@ "repository": {

},
"dependencies": {},
"dependencies": {
"pull-stream": "^3.2.0"
},
"devDependencies": {

@@ -13,0 +15,0 @@ "tape": "^4.4.0"

@@ -6,4 +6,265 @@ # map-filter-reduce

## example
count the total number of mentions in ssb.
``` js
var mfr = require('map-filter-reduce')
pull(
ssbc.createLogStream(),
mfr([
//get all posts.
{$filter: { value: { content: { type: 'post' } } }},
//extract the mentions
{$map: {mentions: ['value', 'content', 'mentions', 'length']}},
//sum all the lengths
{$reduce: {$sum: true}}
])
pull.log()
)
```
This example uses a full scan, so it looks at every object in the
database. for a more efficient way to do the same thing,
see [streamview-links](https://github.com/dominictarr/streamview-links)
## processing streams
`map-filter-reduce` provides three functional stream processing
operators. usually, generally, filter should be used first,
then map then reduce, but operators can be combined in any order,
and used any number of times.
### filter
a filter removes items from an incoming stream.
#### basic values: strings, numbers, booleans
strings, numbers and booleans match exactly.
``` js
{$filter: 'okay'}
```
matches all strings that equal `"okay"`
#### $prefix
`$prefix` operator matches strings that start with a given string.
``` js
{$prefix: 'o'}
```
this will match `"okay"` `"ok"` `"oh no"`, etc.
#### $gt, $lt, $gte, $lte
match values that are greater than, less than, greater than or equal, or less than or equal.
A greater operator and a lesser operator may be combined into one comparison.
``` js
{$gte: 0, $lt: 1}
```
will filter numbers from 0 up to but not including 1.
#### objects
an object is used to filter objects that have the same properties.
an object is combined with other operators that apply to the keys.
``` js
{name: {$prefix: 'bob'}, age: {$gt: 10}}
```
select "bob", "bobby", and "bobalobadingdog", if their age is greater than 10.
#### arrays
arrays are like objects, but their keys are compared in order from left to right.
TODO: implement prefix and ltgt ranges on arrays.
### map
If the incoming stream has fields you are not interested in,
or fields that you'd like to remap, you can _map_ those objects.
lets say, we have a nested object incoming, but we just want to pluck off
the a nested name field.
``` js
{name: ['value', 'name']}
```
#### key: strings, numbers
strings and numbers are used to get keys off the input.
``` js
'value'
```
would return the value property of the input, and drop the rest.
use numbers (integers) if the input will be an array.
#### keys: objects
for a {} object, each value is considered a rule, and applied to
the value of the incoming data. a value with the transformations applied
will be returned.
the keys in the object do not need to be the same as in the input,
since the values will map to which keys to operate on from the input.
``` js
{foo: 'bar', bar: 'foo'}
```
transform the input stream into a stream with `foo` and `bar` keys switched,
and any other keys dropped.
#### path: arrays
arrays are used to lookup deep into an object. they are analogous to useing
chaining dots in javascript.
``` js
['value', 'name']
```
get the value property, and then get the name property off that.
### reduce
reduce is used to aggregate many values into a representative value.
`count`, `sum`, `min`, `max`, and `group` are all reduces.
#### count
count how many items are in the input
``` js
{$count: true}
```
#### sum
sum elements in the input. input elements must be numbers.
sums can be applied to paths, or strings to get the values to sum.
add up all the values for `value.age`
``` js
{$sum: ['value', 'age']}
```
#### min, max
get the minimum or maximum for a value.
``` js
{$min: ['value', 'age']}
```
#### collect
get all values an put them into an array.
get all values for `foo`
``` js
{$collect: 'foo'}
```
this may produce a large value if there are many items in the input stream.
#### objects
to apply multiple reduce functions, put them in an object with
key names.
``` js
{
youngest: {$min: ['value','age']},
oldest: {$max: ['value', 'age']}
}
```
#### group
group the input into sections. group is used with other reducers,
first group splits the input into groups, and then runs the reducers
on the elements in that group.
``` js
{
$group: 'country',
$count: true
}
```
count items per country. will give a single output, that is an object
where each value for `country` in the input becomes a key.
say, if the inputs values for country where `nz, us, de, au` then the
output might be:
``` js
{
nz: 2,
us: 4,
de: 2,
au: 1
}
```
group can be applied to more than one field by using an array.
``` js
{$group: ['country', 'city'], $count: true}
```
would return an object nested to two levels, by country, then city
Note that in group, arrays are used for a list of groups,
instead of paths, to get a path, use an array inside an array!
``` js
{$group: [['value', 'name']], $count: true}
```
since groups are also just reduces, they can be nested by using
object keys. this lets us apply aggregation on different levels.
``` js
{$group: 'country',
count: {$count: true},
city: {
$group: [['country', 'city']],
$count: true
}
}
```
the output might look like this:
``` js
{
nz: {
count: 2,
city: {akl: 1, wlg: 1},
},
us: {
count: 4,
city: {nyc: 1, aus: 1, sfo: 1, pdx: 1}
},
de: {
count: 2, city: {ber: 2}
},
au: {
count: 1, city: {syd: 1}
}
}
```
TODO: group by time ranges (day, month, week, year, etc)
## License
MIT

@@ -26,12 +26,2 @@ var u = require('./util')

function make (query) {
var k = isSimple(query)
if(k) return lookup(simple[k], query[k])
else if(u.isObject(query))
return multi(map(query, function (q, k) {
if(k == '$group') return undefined
return make(query[k])
}))
}
function each(list, iter) {

@@ -57,5 +47,19 @@ if(u.isString(list)) return iter(list)

module.exports = function reduce (query) {
return query.$group ? group(query.$group, make(query)) : make(query)
function make (query) {
var k = isSimple(query)
if(k) return lookup(simple[k], query[k])
else if(u.isObject(query))
return multi(map(query, function (q, k) {
if(k == '$group') return undefined
return gmake(query[k])
}))
}
function gmake (query) {
return query.$group ? group(query.$group, make(query)) : make(query)
}
module.exports = gmake

@@ -117,1 +117,14 @@ var tape = require('tape')

tape('nested groups', function (t) {
t.deepEqual(
groups.reduce(R({
$group: 'country',
population: {$count: true},
housing: {$group: 'house', $count: true}
}), null),
{ US: { population: 3, housing: { apartment: 2, house: 1 } },
NZ: { population: 2, housing: { house: 1, sailboat: 1 } } }
)
t.end()
})
SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc