In Redis, I have hash keys in the following format
keys {
'img::opt': 'nameX',
'img:*:opt': 'nameY',
'img:#:opt': 'nameZ',
'img:A:opt': 'nameN'
}
It is actually in the format of 'extension:owner:spec'
I want to perform hscan based on owner which returns,
1. Everything except blank(will return 2nd, 3rd and 4th keys)
2. Only blank and star(*)(will return 1st and 2nd keys)
For first, I can use pattern as 'img:?*:opt'. How to write a pattern which can be used for 2nd case.
I tried,
img:[^][*]:opt
img:[^|*]:opt
img:[*^]:opt
But none of them are working. Is it possible to pattern match empty string?
Redis' glob-style pattern matching syntax doesn't support the not ('^') operator.
However, as you're looking for two specific keys, why not access them directly by simply doing:
HGET img:*:opt img::opt
Note: in Redis versions prior to 4, HGET needs to be replaced with HMGET
Related
I have string output:
1 4 2 1 4
I want to get each character in string to compare.
I did it to want to know whether the list is sorted yet.
It's not exactly clear to me what you are trying to achieve. Going by "to know whether the list is sorted", and assuming a list of integers, you can use tcl::mathop::< or tcl::mathop::<=, depending on whether you want to allow duplicate values:
if {[tcl::mathop::<= {*}$list]} {
puts "List is sorted"
} else {
puts "List is mixed up"
}
This will also work for ASCII comparison of strings. For more complex comparisons, like using dictionary rules or case insensitive, it's probably easiest to combine that with lsort along with the -indices option:
tcl::mathop::< {*}[lsort -indices -dictionary $list]
The -indices option returns the original index of each list element in sorted order. By checking if those indices are in incremental order, you know if the original list was already sorted.
Of course, if the point of the exercise was to avoid unnecessary sorting, then this is no use. But then again, bubble sort of an already sorted list is very fast and will basically do exactly the comparisons you described. So just sorting will probably be faster than first checking for a sorted list via a scripted loop.
To get each character in the string, do split $the_string "" (yes, on the empty string). That gives you a list of all the characters in the string; you can use foreach to iterate over them. Remember, you can iterate over two (or more) lists at once:
foreach c1 [split $the_string ""] c2 $target_comparison_list {
if {$c1 ne $c2} {
puts "The first not equal character is “$c1” when “$c2” was expected"
break
}
}
Note that it's rarely useful to continue comparison after a difference is found as the most common differences are (relative to the target string) insertions and deletions; almost everything after either of those will differ.
I'm new to Aerospike and am probably missing something fundamental, but I'm trying to see an enumeration of the Keys in a Set (I'm purposefully avoiding the word "list" because it's a datatype).
For example,
To see all the Namespaces, the docs say to use SHOW NAMESPACES
To see all the Sets, we can use SHOW SETS
If I want to see all the unique Keys in a Set ... what command can I use?
It seems like one can use client.scan() ... but that seems like a super heavy way to get just the key (since it fetches all the bin data as well).
Any recommendations are appreciated! As of right now, I'm thinking of inserting (deleting) into (from) a meta-record.
Thank you #pgupta for pointing me in the right direction.
This actually has two parts:
In order to retrieve original keys from the server, one must -- during put() calls -- set policy to save the key value server-side (otherwise, it seems only a digest/hash is stored?).
Here's an example in Python:
aerospike_client.put(key, {'bin': 'value'}, policy={'key': aerospike.POLICY_KEY_SEND})
Then (modified Aerospike's own documentation), you perform a scan and set the policy to not return the bin data. From this, you can extract the keys:
Example:
keys = []
scan = client.scan('namespace', 'set')
scan_opts = { 'concurrent': True, 'nobins': True, 'priority': aerospike.SCAN_PRIORITY_MEDIUM }
for x in (scan.results(policy=scan_opts)): keys.append(x[0][2])
The need to iterate over the result still seems a little clunky to me; I still think that using a 'master-key' Record to store a list of all the other keys will be more performant, in my case -- in this way, I can simply make one get() call to the Aerospike server to retrieve the list.
You can choose not bring the data back by setting includeBinData in ScanPolicy to false.
I don't fully understand, why the results are different here. Does :ov apply only to <left>, so having found the longest match it wouldn't do anything else?
my regex left {
a | ab
}
my regex right {
bc | c
}
"abc" ~~ m:ex/<left><right>
{put $<left>, '|', $<right>}/; # 'ab|c' and 'a|bc'
say '---';
"abc" ~~ m:ov/<left><right>
{put $<left>, '|', $<right>}/; # only 'ab|c'
Types of adverbs
It's important to understand that there are two different types of regex adverbs:
Those that fine-tune how your regex code is compiled (e.g. :sigspace/:s, :ignorecase/:i, ...). These can also be written inside the regex, and only apply to the rest of their lexical scope within the regex.
Those that control how regex matches are found and returned (e.g. :exhaustive/:ex, :overlap/:ov, :global/:g). These apply to a given regex matching operation as a whole, and have to be written outside the regex, as an adverb of the m// operator or .match method.
Match adverbs
Here is what the relevant adverbs of the second type do:
m:ex/.../ finds every possible match at every possible starting position.
m:ov/.../ finds the first possible match at every possible starting position.
m:g/.../ finds the first possible match at every possible starting position that comes after the end of the previous match (i.e., non-overlapping).
m/.../ finds the first possible match at the first possible starting position.
(In each case, the regex engine moves on as soon as it has found what it was meant to find at any given position, that's why you don't see additional output even by putting print statements inside the regexes.)
Your example
In your case, there are only two possible matches: ab|c and a|bc.
Both start at the same position in the input string, namely at position 0.
So only m:ex/.../ will find both of them – all the other variants will only find one of them and then move on.
:ex will find all possible combinations of overlapping matches.
:ov acts like :ex except that it limits the search algorithm by constraining it to find only a single match for a given starting position, causing it to produce a single match for a given length. :ex is allowed to start from the very beginning of the string to find a new unique match, and so it may find several matches of length 3; :ov will only ever find exactly one match of length 3.
Documentation:
https://docs.perl6.org/language/regexes
Exhaustive:
To find all possible matches of a regex – including overlapping ones – and several ones that start at the same position, use the :exhaustive (short :ex) adverb
Overlapping:
To get several matches, including overlapping matches, but only one (the longest) from each starting position, specify the :overlap (short :ov) adverb:
I tried adding some sample score-value pairs to redis sorted set using below code:
String key = "set";
redis.zadd(key, 5, "1034");
redis.zadd(key, 2, "1030");
redis.zadd(key, 1, "1089");
and tried retrieving it using byteArray and BitSet
byte[] byteArr = redis.get(key.getBytes());
BitSet bitSet = fromByteArrayReverse(byteArr);
System.out.println(bitset.toString()));
also i tried executing
System.out.println(redis.get(key.getBytes()));
which is supposed to give me an address of the byte-array
But for both of these commands i get the error
" ERR Operation against a key holding the wrong kind of value"
So can anyone please tell me why does this error occur in the first place and also the correct redis command/code to retrieve values from a redis sorted-set??
What you want is calling
ZSCORE key "1034"
Or in the case of wanting only elements between two particular scores
ZRANGEBYSCORE key lower upper
Since you also have "rank" (position or index, as in a list) you can also ask for example for the first three elements in your set
ZRANGEBYRANK key 0 2
The error you are getting is because once you assign a value to a key, that value defines the type of the internal structure on redis, and you can only use commands for that particular structure (or generic key commands such as DEL and so on). In your case you are trying to mix sorted sets with byte operations and it doesn't match.
To see all sorted set commands, please refer to http://redis.io/commands#sorted_set
I'd like to create a regular expression such that when I compare the a string against an array of strings, matches are returned with the regex ignoring certain characters.
Here's one example. Consider the following array of names:
{
"Andy O'Brien",
"Bob O'Brian",
"Jim OBrien",
"Larry Oberlin"
}
If a user enters "ob", I'd like the app to apply a regex predicate to the array and all of the names in the above array would match (e.g. the ' is ignored).
I know I can run the match twice, first against each name and second against each name with the ignored chars stripped from the string. I'd rather this by done by a single regex so I don't need two passes.
Is this possible? This is for an iOS app and I'm using NSPredicate.
EDIT: clarification on use
From the initial answers I realized I wasn't clear. The example above is a specific one. I need a general solution where the array of names is a large array with diverse names and the string I am matching against is entered by the user. So I can't hard code the regex like [o]'?[b].
Also, I know how to do case-insensitive searches so don't need the answer to focus on that. Just need a solution to ignore the chars I don't want to match against.
Since you have discarded all the answers showing the ways it can be done, you are left with the answer:
NO, this cannot be done. Regex does not have an option to 'ignore' characters. Your only options are to modify the regex to match them, or to do a pass on your source text to get rid of the characters you want to ignore and then match against that. (Of course, then you may have the problem of correlating your 'cleaned' text with the actual source text.)
If I understand correctly, you want a way to match the characters "ob" 1) regardless of capitalization, and 2) regardless of whether there is an apostrophe in between them. That should be easy enough.
1) Use a case-insensitivity modifier, or use a regexp that specifies that the capital and lowercase version of the letter are both acceptable: [Oo][Bb]
2) Use the ? modifier to indicate that a character may be present either one or zero times. o'?b will match both "o'b" and "ob". If you want to include other characters that may or may not be present, you can group them with the apostrophe. For example, o['-~]?b will match "ob", "o'b", "o-b", and "o~b".
So the complete answer would be [Oo]'?[Bb].
Update: The OP asked for a solution that would cause the given character to be ignored in an arbitrary search string. You can do this by inserting '? after every character of the search string. For example, if you were given the search string oleary, you'd transform it into o'?l'?e'?a'?r'?y'?. Foolproof, though probably not optimal for performance. Note that this would match "o'leary" but also "o'lea'r'y'" if that's a concern.
In this particular case, just throw the set of characters into the middle of the regex as optional. This works specifically because you have only two characters in your match string, otherwise the regex might get a bit verbose. For example, match case-insensitive against:
o[']*b
You can add more characters to that character class in the middle to ignore them. Note that the * matches any number of characters (so O'''Brien will match) - for a single instance, change to ?:
o[']?b
You can make particular characters optional with a question mark, which means that it will match whether they're there or not, e.g:
/o\'?b/
Would match all of the above, add .+ to either side to match all other characters, and a space to denote the start of the surname:
/.+? o\'?b.+/
And use the case-insensitivity modifier to make it match regardless of capitalisation.