Hi Marc,
You can use regular expressions as keys in a map like this;
class RegexpMap {
@Delegate Map map
def getAt( String key ) {
map.find { a ->
a.key.matcher( key ).matches()
}.value
}
def putAt( String key, Object value ) {
map.find { a ->
a.key.matcher( key ).matches()
}.value = value
}
}
def map = new RegexpMap( map:[ (~/[a-z]+/):0, (~/[0-9]+/):10, ] )
// Check that alpha keys are 0
assert map[ 'a' ] == 0
assert map[ 'b' ] == 0
// And numeric keys are 10
assert map[ '1' ] == 10
// Set 'a' to 20
map[ 'a' ] = 20
// Check 'a' is 20
assert map[ 'a' ] == 20
// But as you can see, all alpha values are now 20
assert map[ 'b' ] == 20
but this isn't really what you wanted. I don't believe it's possible to
unroll a regexp to get all possible combinations that would pass it (and if
there were, as you say, it could end up consuming all of space-time ;-)
Maybe using something like the class I posted above, but just using a getAt
override to return a default value if the property had never been set?
Something like:
import java.util.regex.Pattern
class FunkyMap {
Pattern initialPattern
def initialValue
@Delegate Map map = [:]
def getAt( String key ) {
map[ key ] ?: ( initialPattern.matcher( key ).matches() ? initialValue :
null )
}
}
def map = new FunkyMap( initialValue:10, initialPattern:(~/[a-z]+/) )
assert map[ 1 ] == null
assert map[ 'a' ] == 10
So that creates a class with a regexp and a default value. If the key is
null, and matches the regexp, then the default value is returned
Hope this helps...
Tim
Post by marc fawziHey Tim,
This is really nice.
Let's say that I want to define a map that has regex pattern as a key
initialized to 0, e.g.
def map = [ /pattern/ : '0' ]
Obviously, if the pattern matches any string (e.g: /.*/ ) then the map
can't be created because it would consume the spacetime continuum :) but I
guess my question was exactly about that, although I did found your
ReplaceByRegexp function is quite useful in the context of what I'm trying
to do)
Now, if it is possible to pre-define a map and not have it be created per
se (i.e. just a place holder that says this 'map' contains a regex pattern
as key so don't create it just yet) and then have the map be _created and
appended to or modified as you specify a literal key to update_ e.g.
"this_is_a_key_that_matches_the_regex_pattern" and I like to update its'
value from 0 to X. So as I go on specifying literal keys to update within
that pre-defined map the map is actually created (on first such update) and
appended to or modified on every following update.
I guess what I'm looking for may not be a map. I just need a key-value data
structure that I can pre-define using regex keys (set to e.g. 0) and then
create and update that key-value structure by specifying the literal key. So
for a key that is pre-defined as /[regex pattern for banana or bananas]/ I
want to be able to update the key "banana". In my case, the key-value data
structure would be more like a template where keys are not defined until
they're explicitly specified during being updated.
How do I go about doing this?
Thanks in advance for any tips or for helping me think about it
differently. :)
Being a n00b is a full time job.
Marc
Post by Tim YatesDoes this fit the bill?
There may be a better way of doing it...
def map = [ 'a'..'z', 1, 2, 3 ].flatten().inject( [:] ) { map, val ->
map[ val ] = 0
map
}
// This will do the replacement. It alters the original map
def replaceByRegexp( Map map, regexp, value ) {
map.each { k, v ->
// If the key matches the regexp, then set the map entry to our value
if( k ==~ regexp ) map[ k ] = value
}
}
// Replace keys a, c anf f
replaceByRegexp( map, /[acf]/, 20 )
Tim
Post by marc fawzi(new to groovy)
Can I have a list/range, e.g. [a..z], or some regex pattern inside a map
to define the keys so that I don't have to spell them out when initializing?
Example: how do I replace XXXX with [a..z]
def someMap = [
XXXX:0,
1:0,
2:0,
3:0,
]
This way I don't have to specify the keys "a" thru "z" by hand
How do I initialize multiple keys to one value inside a map using a list
of keys?
Also, how do I initialize multiple keys to one value inside a map using a
regex pattern (for the keys)?
Thanks!
Marc