How to test whether an element exists in list? - list

Is there a way how to test whether an element exists in list?
$ qore -nX 'boolean(select ("a", "b", "c"), $1 === "a")'
This solution creates a new list only to test its size...

If the elements are not repeated, then your solution is not bad, as only a single element list would be returned.
For a more efficient general solution, you can use the foldl and map operators together, both of which support lazy functional evaluation, so no intermediate lists will be created during the execution of the compound expression.
For example:
$ qore -nX '(foldl $1 + $2, (map 1, ("a", "b", "c", "a"), $1 === "z")).toBool()'
False
$ qore -nX '(foldl $1 + $2, (map 1, ("a", "b", "c", "a"), $1 === "a")).toBool()'
True
Note that you can take away the .toBool() pseudo-method call in the above expressions to get the count of occurrences of the element in the list directly. One drawback of this solution, however, is that it scans the entire list instead of stopping as soon as the first match is found.

There is actually a language function for this! inlist and inlist_hard

Related

Output list with first match among two list

I have two lists in Tcl:
list1
{a/1 a/2 b/1 b/2}
list2
{a b}
I wanted to write a code which will check an element from list2 in list1 and give the first match and ignores the rest of the matches, basically below output list:
a/1 b/1
The only tricky bit in this is knowing exactly how the items in list 2 are to be searched for in list 1. I'm going to assume they're fairly simple strings and that we can just glob match for them (as if with string match). That's a case that lsearch supports by default, allowing us to use a pretty simple bit of code:
proc FirstMatches {haystackList needlesList} {
lmap needle $needlesList {
lsearch -inline $haystackList $needle*
}
}
puts [FirstMatches {a/1 a/2 b/1 b/2} {a b}]
The lmap just runs its body (as with foreach) for every needle in $needleList and collects the results of that into a list. It's perfect here.

Why does special characters in my variable disappear on doing an lindex in TCL?

I have a list in my application that i work on.. Its basically like this:
$item = {text1 text2 text3}
Then I pick up the first member in the list with:
lindex $item 0
On doing this text1 which used to be (say) abcdef\12345 becomes abcdef12345.
But its very important for me to not lose this \ . Why is it disappearing. THere are other characters like - and > which don't disappear. Please note that I cannot escape the \ in the text beforehand. If there's anything I can do before operating on the $item with lindex, please suggest.
The problem is that \ is a Tcl list metasyntax character, unlike -, > or any alphanumeric. You need to convert your string into a proper Tcl list before using lindex (or any other list-consuming operation) on it. To do that, you need to understand exactly what you mean by “words” in your input data. If your input data is a sequences of non-whitespace characters separated by single whitespace characters, you can use split to do the conversion to a list:
set properList [split $item]
# Now we can use it...
set theFirstWord [lindex $properList 0]
If you've got a different separator, split takes an optional extra character to say what to split by. For example, to split by colons (:) you do:
set properList [split $item ":"]
However, if you have other sorts of splitting rules, this doesn't work so well. For example, if you can split by multiple whitespace characters, it's actually better to use regexp (with the -all -inline options) to do the word-identification:
# Strictly, this *chooses* all sequences of one or more non-whitespace characters
set properList [regexp -all -inline {\S+} $item]
You can also do splitting by multi-character sequences, though in that case it is most easily done by mapping (with string map) the multi-character sequence to a single rare character first. Unicode means that there are lots of such characters to pick…
# NUL, \u0000, is a great character to pick for text, and terrible for binary data
# For binary data, choose something beyond \u00ff
set properList [split [string map {"BOUNDARY" "\u0000"} $item] "\u0000"]
Even more complex options are possible, but that's when you use splitx from Tcllib.
package require textutil::split
# Regular expression to describe the separator; very sophisticated approach
set properList [textutil::split::splitx $item {SPL+I*T}]
In tcl Lists can be created in several ways:
by setting a variable to be a list of values
set lst {{item 1} {item 2} {item 3}}
with the split command
set lst [split "item 1.item 2.item 3" "."]
with the list command.
set lst [list "item 1" "item 2" "item 3"]
And an individual list member can be accessed with the lindex command.
set x "a b c"
puts "Item 2 of the list {$x} is: [lindex $x 2]\n"
This will give output:
Item 2 of the list {a b c} is: c
And With respect to the question asked
You need to define the variable like this abcdef\\12345
In order to make this clear try to run the following command.
puts "\nI gave $100.00 to my daughter."
and
puts "\nI gave \$100.00 to my daughter."
The second one will give you the proper result.
If you don't have the option to change the text, try to save the text in curly braces, as mentioned in the first example.
set x {abcd\12345}
puts "A simple substitution: $x\n"
Output:
A simple substitution: abcd\12345
set y [set x {abcdef\12345}]
And check for this output:
puts "Remember that set returns the new value of the variable: X: $x Y: $y\n"
Output:
Remember that set returns the new value of the variable: X: abcdef\12345 Y: abcdef\12345

lsearch does not match elements that require curly-braces (Tcl 8.4)

I'm dealing with a big number of signals. I've been able to store them into a list, but since their name have brackets the signals are store in a list. Latter on, using regexp, I analyze some output produced and, if there's a match, I needed to set a flag.
In this following example I show the element added to the list and, later one, I try to check if the same element is inside of the list using lsearch
set mylist [list]
set element {aux[1]}
lappend mylist $element
puts "mylist: $mylist \nelement: $element\n\[list element\]: [list $element]"
The result of this puts is:
mylist: {aux[1]}
element: aux[1]
[list element]: {aux[1]}
Since my element is stored as {a[1]}, I've not found a way to make lsearch to return a match
set result [lsearch $mylist $element]
set result2 [lsearch $mylist [list $element]]
puts $result
puts $result2
Both results return '-1'.
I've seen solutions, but none of them using Tcl 8.4; And I need to use it due to backwards compatibility.
Use the -exact matching style. The default style is -glob, which means that the substring [1] matches a single 1.
lsearch -exact $mylist $element
# => 0
Documentation: lsearch

Ocaml Pattern Matching

I am pretty new to OCaml and pattern matching, so I was having a hard time trying to figure this out.
Say that I have a list of tuples. What I want to do is match a parameter with one of the tuples based on the first element in the tuple, and upon doing so, I want to return the second element of the tuple. So for example, I want to do something like this:
let list = [ "a", 1; "b", 2; "c", 3; "d", 4 ] ;;
let map_left_to_right e rules = match e with
| first -> second
| first -> second
| first -> second
If I use map_left_to_right "b" list, I want to get 2 in return.
I therefore want to list out all first elements in the list of rules and match the parameter with one of these elements, but I am not sure how to do so. I was thinking that I need to use either List.iter or List.for_all to do something like this. Any help would be appreciated. Thanks!
Pattern matching is intended for cases where you want to match a fixed list of patterns. In your current situation, the idiomatic thing to use is List.assoc:
let map_left_to_right e rules default =
try List.assoc e rules with Not_found -> default
You need to provide a default when the element is not found. Here, map_left_to_right "b" list 0 would return 2 as expected, and map_left_to_right "z" list 0 would return 0.
Match only matches against fixed patterns, not variables. An appropriate use of matching in this case would look like this: (note the inclusion of a "default" just as in the other answer)
let list = [ "a", 1; "b", 2; "c", 3; "d", 4 ]
let rec map_left_to_right e rules default = match rules with
[] -> default (* No rules left to match *)
| (first,second)::rest -> (* At least one rule remaining, which we'll put into first,second *)
if first = e
then second
else map_left_to_right e rest default
If we want to return 0 if nothing is found, then this would be called like so:
map_left_to_right "b" list 0
All of this is functionally equivalent to the code in the other answer, and in practice I would recommend using that code since it's smaller and makes better use of existing libraries, but I thought that I would give this code because it better illustrates how pattern matching would actually be applied in this case.

How can I replace the same string several times with different random values in Perl?

I'm using this Perl one-liner (in bash) to successfully replace a string with a random one, in a given file:
perl -pi -e "s/replace\ this/`</dev/urandom tr -dc A-Za-z0-9 | head -c64`/g" example.php
However, I don't know how to replace several "replace this" with different random strings.
perl -pi -e 's/replace this/join "", map { ("a" .. "z", "A" .. "Z", 0 .. 9)[rand(62)] } 1 .. 64/eg' example.php
Let's break this down into its pieces.
("a" .. "z", "A" .. "Z", 0 .. 9)
is a list that contains the characters you want to be in the random string.
[rand(62)]
This is indexing the list above at a random location (using the rand function). The 62 corresponds to the number of items in the list. The rand function returns a number between zero and the number you gave it minus one. Happily, arrays and lists are indexed starting at zero in Perl 5, so this works out perfectly. So, every time that piece of code is run, you will get one random character from the list of acceptable characters.
The map takes a code block and a list as arguments. It runs the code block and returns the result for every item in the list handed to it. The list is 1 .. 64, so the code block will run sixty-four times. Since the code block contains the code that generates a random character, the result of the map function is sixty-four random characters.
The join function takes a delimiter and a list and returns the list as a string delimited by the delimiter (e.g. join ",", "a", "b", "c" returns "a,b,c"). In this case we are using an empty string as the delimiter, so it just produces a string made up of the characters in the list (i.e. the sixty-four random characters).
Now we are ready to look at the substitution. It looks for every instance (because of the /g option) of the string "replace this" and runs the code in the replacement side (because of the /e options) and replaces the string "replace this" with the value of the last statement executed in the replacement side (in this case, the return value of join).
Then why not write a script
#!/bin/bash
for replace in "replace this" "replace that"
do
rand=$(generate random here using /dev/urandom )
sed -i "s/$replace/$rand/" file
done