mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-29 02:50:10 +00:00
AT(..) now supports patterns in keys or paths + docs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
a559ed7aeb
commit
a70605f742
16
README.md
16
README.md
@ -554,6 +554,22 @@ Matches a *container* if it contains `A`.
|
|||||||
`AT(K, A)`
|
`AT(K, A)`
|
||||||
Matches a *container* if it contains `A` *at* index/key `K`
|
Matches a *container* if it contains `A` *at* index/key `K`
|
||||||
|
|
||||||
|
If `K` is a pattern or a path containing a pattern then matching is done as follows:
|
||||||
|
1. select all keys/paths that match `K`
|
||||||
|
2. get all values at the selected keys/paths
|
||||||
|
3. match iff *all* of the selected values match `A`
|
||||||
|
|
||||||
|
Note that to use an explicit array for `K`, wrap it in an array, e.g. to use `[item, ..]` as key write: `AT([[item, ..]], ..)`.
|
||||||
|
|
||||||
|
`AT(K)`
|
||||||
|
Matches if a *container* has an index/key `K`.
|
||||||
|
|
||||||
|
This is equivalent to `AT(K, ANY)`.
|
||||||
|
|
||||||
|
~~`ORDERED(A, B)`~~
|
||||||
|
|
||||||
|
~~`ADJACENT(A, B, ...)`~~
|
||||||
|
|
||||||
~~`OF(A, N)`~~
|
~~`OF(A, N)`~~
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
97
diff.js
97
diff.js
@ -667,10 +667,11 @@ object.makeConstructor('TEST', Object.assign(Object.create(LogicType.prototype),
|
|||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// IN(A) == L iff A in L
|
// IN(A) == L iff A contained in L
|
||||||
//
|
//
|
||||||
// NOTE: since this can do a search using cmp(..) thid will be slow on
|
// NOTE: since this can do a search using cmp(..) thid will be slow on
|
||||||
// large containers...
|
// large containers...
|
||||||
|
// NOTE: to test if a key exists use AT(key)
|
||||||
var IN =
|
var IN =
|
||||||
module.IN =
|
module.IN =
|
||||||
object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), {
|
object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), {
|
||||||
@ -678,7 +679,7 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), {
|
|||||||
// XXX should we check inherited stuff???
|
// XXX should we check inherited stuff???
|
||||||
__cmp__: function(obj, cmp, context){
|
__cmp__: function(obj, cmp, context){
|
||||||
var p = this.value
|
var p = this.value
|
||||||
return (obj instanceof Map || obj instanceof Set ?
|
return ((obj instanceof Map || obj instanceof Set) ?
|
||||||
[...obj.values()]
|
[...obj.values()]
|
||||||
: [])
|
: [])
|
||||||
.concat(Object.values(obj))
|
.concat(Object.values(obj))
|
||||||
@ -693,7 +694,13 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// AT(A, K) == L iff A in L and L[K] == A
|
// AT(K, A) == L iff A in L and L[K] == A
|
||||||
|
//
|
||||||
|
// If K is a pattern or a path containing a pattern this works in the
|
||||||
|
// following stages:
|
||||||
|
// 1) select all the keys/paths that match K
|
||||||
|
// 2) get all the values at the matching paths
|
||||||
|
// 3) return true if ALL the values match A
|
||||||
//
|
//
|
||||||
// NOTE: this also supports path keys -- i.e. array of path elements that
|
// NOTE: this also supports path keys -- i.e. array of path elements that
|
||||||
// will be traversed and the last one checked...
|
// will be traversed and the last one checked...
|
||||||
@ -701,10 +708,10 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), {
|
|||||||
// an array:
|
// an array:
|
||||||
// AT([[123]], ...)
|
// AT([[123]], ...)
|
||||||
//
|
//
|
||||||
// XXX .key can't be a pattern at this point...
|
// XXX pattern keys are still experimental, and the exact matching rules
|
||||||
// ...to implement this we would need to do:
|
// may still change...
|
||||||
// 1) a search for a matching pattern...
|
// ...not yet sure if on step #3 we should require ALL or at least
|
||||||
// 2) handle multiple matches in some manner (first, all?)...
|
// one match, though I'm leaning towards ALL...
|
||||||
// XXX this falls into recursion on:
|
// XXX this falls into recursion on:
|
||||||
// X = AT('moo')
|
// X = AT('moo')
|
||||||
// X.value = OR(123, X)
|
// X.value = OR(123, X)
|
||||||
@ -717,23 +724,79 @@ module.AT =
|
|||||||
object.makeConstructor('AT', Object.assign(Object.create(LogicType.prototype), {
|
object.makeConstructor('AT', Object.assign(Object.create(LogicType.prototype), {
|
||||||
__cmp__: function(obj, cmp, context){
|
__cmp__: function(obj, cmp, context){
|
||||||
var key = this.key instanceof Array ? this.key : [this.key]
|
var key = this.key instanceof Array ? this.key : [this.key]
|
||||||
var no_result = {}
|
var value = this.value
|
||||||
obj = key
|
//return key
|
||||||
|
var res = key
|
||||||
.reduce(function(o, k){
|
.reduce(function(o, k){
|
||||||
return (o == null || o === no_result) ?
|
return o
|
||||||
no_result
|
.map(function(o){
|
||||||
: o[k] }, obj)
|
return o == null ?
|
||||||
if(obj !== no_result && cmp(obj, this.value, context)){
|
[]
|
||||||
return true
|
// pattern key,,,
|
||||||
}
|
: k instanceof LogicType ?
|
||||||
return false
|
Object.entries(o)
|
||||||
|
.filter(function(e){
|
||||||
|
return cmp(k, e[0], context) })
|
||||||
|
.map(function(e){
|
||||||
|
return e[1] })
|
||||||
|
// normal key...
|
||||||
|
// NOTE: we are not using 'k in o' here because
|
||||||
|
// only objects are supported by the in
|
||||||
|
// operator and we can get any value...
|
||||||
|
: Object.keys(o).indexOf(k) >= 0 ?
|
||||||
|
[o[k]]
|
||||||
|
// key not in container...
|
||||||
|
: [] })
|
||||||
|
// flatten the list of candidates...
|
||||||
|
.reduce(function(o, e){
|
||||||
|
return o.concat(e) }, []) }, [obj])
|
||||||
|
/*
|
||||||
|
.filter(function(e){
|
||||||
|
return cmp(e, value, context)})
|
||||||
|
// at least one must match...
|
||||||
|
.length > 0
|
||||||
|
//*/
|
||||||
|
return obj != null
|
||||||
|
&& res.length > 0
|
||||||
|
&& res
|
||||||
|
.filter(function(e){
|
||||||
|
return cmp(e, value, context)})
|
||||||
|
// all must match...
|
||||||
|
.length == res.length
|
||||||
},
|
},
|
||||||
__init__: function(key, value){
|
__init__: function(key, value){
|
||||||
this.key = key
|
this.key = key
|
||||||
this.value = value
|
this.value = arguments.length < 2 ? ANY : value
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// XXX ORDERED(A, B, ..) == L iff A is before B, B is before C, ... etc.
|
||||||
|
var ORDERED =
|
||||||
|
module.ORDERED =
|
||||||
|
object.makeConstructor('ORDERED', Object.assign(Object.create(LogicType.prototype), {
|
||||||
|
__cmp__: function(obj, cmp){
|
||||||
|
// XXX
|
||||||
|
},
|
||||||
|
__init__: function(...items){
|
||||||
|
this.items = items
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// XXX ADJACENT(A, B, ..) == L iff A directly before B, B directly before C, ...
|
||||||
|
var ADJACENT =
|
||||||
|
module.ADJACENT =
|
||||||
|
object.makeConstructor('ADJACENT', Object.assign(Object.create(LogicType.prototype), {
|
||||||
|
__cmp__: function(obj, cmp){
|
||||||
|
// XXX
|
||||||
|
},
|
||||||
|
__init__: function(...items){
|
||||||
|
this.items = items
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// XXX OF(A, N) == L iff L contains N occurrences of A
|
// XXX OF(A, N) == L iff L contains N occurrences of A
|
||||||
// XXX this is a potential problem as it would require us to look ahead
|
// XXX this is a potential problem as it would require us to look ahead
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user