TCL foreach to keep track of index - foreach

When using foreach in TCL to loop through a list it is desired to have a running number of the index of the current object. A way I have done this before is to maintain an extra counter variable.
set ct 0
foreach x $list {
puts "Items is $x index is $ct"
incr ct
}
One could use lsreach to retrieve the index but that's compute intensive and could be problematic with double occurrences.
Wondering if there is streamlined sleek-looking way of maintaining index information during a loop.
Pseudocode :
foreach x $list {
puts "Items is $x index is [foreach_index $x]"
}
Your feedback is appreciated.
UPDATE:
Run time tests with the provided answers:
Peter Lewerin : 86098.8 microseconds per iteration
Gert : 91057.4 microseconds per iteration
David B : 115860.0 microseconds per iteration
Loop through list with 100k random strings 80char long.
The loop proc is fastest, but hard to read.

While the control structure definitions in other languages are the law, in Tcl they're more like a set of guidelines.
proc foreachWithIndex {indexVar args} {
upvar 1 $indexVar var
set var 0
uplevel 1 [list foreach {*}[lrange $args 0 end-1] "[lindex $args end];incr $indexVar"]
}
foreachWithIndex x v {a b c} {puts "$x: $v"}
But I suggest using for instead. Radical language modifications are fun and occasionally useful, but if I had an Imperial credit for every such clever construct I ended up throwing away later I could build my own Death Star and still have money to put a grating over the exhaust port.

Your method of using incr with a counter works ok. This also works:
for { set i 0 } { $i < [llength $list] } { incr i } {
set x [lindex $list $i]
puts "Items is $x index is $i"
}
Another advantage of doing it this way is that you can modify the list while you are iterating. Let's say you want to remove all items with the value "bad" from a list.
set values { 1 2 3 bad 4 bad bad 5 }
for { set i 0 } { $i < [llength $values] } { incr i } {
if { [lindex $values $i] eq "bad" } {
set values [lreplace $values $i $i]
incr i -1
}
}
puts $values

Related

How to check this sequence element is equal to that sequence element in Dafny

I have 2 sequences a:seq and b:seq, I wonder if we use the function, how we can determine that the element at this index in seq a is equal to element at this index in seq b
function test(s:seq<nat>, u:seq<nat>): nat
ensures |s|>0
ensures |u|>0
ensures |s| == |u|
{
// Code
}
method Testing()
{
var sys:seq<nat> := [4,2,9,3,1];
var usr:seq<nat> := [1,2,3,4,5];
assert test(sys, usr) == 1
// The element at the index 2 of sys and usr are equal, so it have 1 element that match in both 2 sequence
}
Because of the function I could not create a while loop, so I can not do the basic logic on that, so I wonder if there's something that fit the requirement.
After researching and working by Python to find the recursion in Python, finally I found the answer for this:
function bullspec(s:seq<nat>, u:seq<nat>): nat
requires |s| > 0
requires |u| > 0
requires |s| == |u|
{
var index:=0;
if |s| == 1 then (
if s[0]==u[0]
then 1 else 0
) else (
if s[index] != u[index]
then bullspec(s[index+1..],u[index+1..])
else 1+bullspec(s[index+1..],u[index+1..])
)
}
This is a wonderful problem to solve with Dafny.
Let me state the problem in clear:
Given two sequences of the same length, find the first index at which these sequences are equal. Otherwise return the length of the sequences.
That formulation makes it possible to not require that sequences are non-empty.
Thus, we can start with the following definition
function bullspec(s:seq<nat>, u:seq<nat>): (r: nat)
requires |s| == |u|
// Ensures r is either a sequence index or the sequence length
ensures r <= |s|
// All the elements before r are different
ensures forall i: nat | i < r :: s[i] != u[i]
// Either r is the sequence length or the elements at index r are equal
ensures r == |s| || s[r] == u[r]
{
Now, if you manage to prove this function, you will have prove that this function does what you want it to do.
To obtain the body of the function, you usually have to check whether the sequence if empty. In our case, we can return 0, which is the length of the sequence.
if |s| == 0 then 0 else
If the sequence is not empty, then we can compare the first elements. If they are equal, then we return the index 0
if s[0] == u[0] then 0 else
Otherwise, what happens if we recurse into bullspec(s[1..],u[1..])? We will obtain an index that is offset by 1 ! So we only need to add 1 to it.
1 + bullspec(s[1..],u[1..])
}
With this, you can verify that your function does exactly what you intended it to do.

How to return values from foreach loop in tcl

I have a list of all the files in the directory. I have stored them in a variable file_list. I want to get the tail name for each file. My approach is like this.
set file_list [list /a/b/a.txt /a/b/b.txt /a/b/c/file1.tcl /a/b/c/file2.tcl]
proc file_tail {filename} {
set x {}
set f_tail [file tail $filename]
lappend x $f_tail
return $x
}
foreach ft $file_list {
set f_tail [file_tail $ft]
}
but f_tail only contains last value stored i.e. "file2.tcl" Please guide me. I want a list of all tail values of file
I suggest either:
set f_tail {}
foreach ft $file_list {
lappend f_tail [file_tail $ft]
}
or (if you have a later version of Tcl):
set f_tail [lmap ft $file_list {file_tail $ft}]
Documentation:
foreach,
lappend,
lmap (for Tcl 8.5),
lmap
If you are making a list of all the tails, do this:
set f_tail {}
foreach ft $file_list {
lappend f_tail [file tail $ft]
}
If your helper function is going to do the lappend, you need to keep the variable holding the list outside the procedure:
proc file_tail {filename listVariable} {
upvar 1 $listVariable theList
set f_tail [file tail $filename]
lappend theList $f_tail
}
set tails {}
foreach ft $file_list {
file_tail $ft tails ; # <<< NAME, so not $tails as that would READ the variable
}
Note that we are passing in the name of the variable (tails outside) and using upvar 1 inside the procedure to make a linked local variable (theList inside) that can be updated. However, you can't do it by passing in a list value; Tcl uses copy-on-write semantics for its values. You need to be careful about the difference between the names of variables and the values they contain; they're not the same.

tcl loop through multiple lists

I have two lists I'd like manipulate.. ( I am a tcl newbie..). I'd like to associate these two lists and create a third list with some data added.
The data I have:
set aes {ae0 ae3 ae6 ae1v1 ae1v8}
set c {c1 c2 c3 k1 k2}
foreach A $aes {
foreach C $c {
puts ${A}_$C
}
}
The data I get as you'd expect is:
ae0_c1
ae0_c2
ae0_c3
ae0_k1
ae0_k2
..
..
What I want to do is
append some data in front of this.
AE-To-c = All ae0_c1 ae0_c2 ae0_c3 ae0_k1 ae0_k2 .. End.
% set aes {ae0 ae3 ae6 ae1v1 ae1v8}
ae0 ae3 ae6 ae1v1 ae1v8
% set c {c1 c2 c3 k1 k2}
c1 c2 c3 k1 k2
% foreach A $aes {
foreach C $c {
# saving into 'result' variable
lappend result ${A}_${C}
}
}
% set data "some more here"
some more here
% set result
ae0_c1 ae0_c2 ae0_c3 ae0_k1 ae0_k2 ae3_c1 ae3_c2 ae3_c3 ae3_k1 ae3_k2 ae6_c1 ae6_c2 ae6_c3 ae6_k1 ae6_k2 ae1v1_c1 ae1v1_c2 ae1v1_c3 ae1v1_k1 ae1v1_k2 ae1v8_c1 ae1v8_c2 ae1v8_c3 ae1v8_k1 ae1v8_k2
% set result [linsert $result 0 $data]
some more here ae0_c1 ae0_c2 ae0_c3 ae0_k1 ae0_k2 ae3_c1 ae3_c2 ae3_c3 ae3_k1 ae3_k2 ae6_c1 ae6_c2 ae6_c3 ae6_k1 ae6_k2 ae1v1_c1 ae1v1_c2 ae1v1_c3 ae1v1_k1 ae1v1_k2 ae1v8_c1 ae1v8_c2 ae1v8_c3 ae1v8_k1 ae1v8_k2
Your question isn't 100% clear. Is it something like this you want?
set res [list AE-To-c = All]
foreach A $aes {
foreach C $c {
lappend res ${A}_$C
}
}
lappend res End
If you want to do what I think you want to do, you need to capture the permutations of the two lists in a list instead of printing them out, and then wrap that list in a prefix and suffix.
The method above pre-loads the result list with the AE-To-c = All prefix, then picks up the permutations using lappend, and finally adds the End suffix as a last element in the list.
Another way:
set res [list]
foreach A $aes {
foreach C $c {
lappend res ${A}_$C
}
}
concat [list AE-To-c = All] $res End
In this variant the list of permutations is created first, and then the prefix list, the permutation list, and the suffix list (yes, End is a list) are concatenated into one flat list.
Documentation: concat, foreach, lappend, list, set

Closure Return Statement does not exit Method [duplicate]

Is it possible to break from a Groovy .each{Closure}, or should I be using a classic loop instead?
Nope, you can't abort an "each" without throwing an exception. You likely want a classic loop if you want the break to abort under a particular condition.
Alternatively, you could use a "find" closure instead of an each and return true when you would have done a break.
This example will abort before processing the whole list:
def a = [1, 2, 3, 4, 5, 6, 7]
a.find {
if (it > 5) return true // break
println it // do the stuff that you wanted to before break
return false // keep looping
}
Prints
1
2
3
4
5
but doesn't print 6 or 7.
It's also really easy to write your own iterator methods with custom break behavior that accept closures:
List.metaClass.eachUntilGreaterThanFive = { closure ->
for ( value in delegate ) {
if ( value > 5 ) break
closure(value)
}
}
def a = [1, 2, 3, 4, 5, 6, 7]
a.eachUntilGreaterThanFive {
println it
}
Also prints:
1
2
3
4
5
Replace each loop with any closure.
def list = [1, 2, 3, 4, 5]
list.any { element ->
if (element == 2)
return // continue
println element
if (element == 3)
return true // break
}
Output
1
3
No, you can't break from a closure in Groovy without throwing an exception. Also, you shouldn't use exceptions for control flow.
If you find yourself wanting to break out of a closure you should probably first think about why you want to do this and not how to do it. The first thing to consider could be the substitution of the closure in question with one of Groovy's (conceptual) higher order functions. The following example:
for ( i in 1..10) { if (i < 5) println i; else return}
becomes
(1..10).each{if (it < 5) println it}
becomes
(1..10).findAll{it < 5}.each{println it}
which also helps clarity. It states the intent of your code much better.
The potential drawback in the shown examples is that iteration only stops early in the first example. If you have performance considerations you might want to stop it right then and there.
However, for most use cases that involve iterations you can usually resort to one of Groovy's find, grep, collect, inject, etc. methods. They usually take some "configuration" and then "know" how to do the iteration for you, so that you can actually avoid imperative looping wherever possible.
Just using special Closure
// declare and implement:
def eachWithBreak = { list, Closure c ->
boolean bBreak = false
list.each() { it ->
if (bBreak) return
bBreak = c(it)
}
}
def list = [1,2,3,4,5,6]
eachWithBreak list, { it ->
if (it > 3) return true // break 'eachWithBreak'
println it
return false // next it
}
You can't break from a Groovy each loop, but you can break from a java "enhanced" for loop.
def a = [1, 2, 3, 4, 5, 6, 7]
for (def i : a) {
if (i < 2)
continue
if (i > 5)
break
println i
}
Output:
2
3
4
5
This might not fit for absolutely every situation but it's helped for me :)
I agree with other answers not to use an exception to break an each. I also do not prefer to create an extra closure eachWithBreak, instead of this I prefer a modern approach: let's use the each to iterate over the collection, as requested, but refine the collection to contain only those elements to be iterated, for example with findAll:
collection.findAll { !endCondition }.each { doSomething() }
For example, if we what to break when the counter == 3 we can write this code (already suggested):
(0..5)
.findAll { it < 3 }
.each { println it }
This will output
0
1
2
So far so good, but you will notice a small discrepancy though. Our end condition, negation of counter == 3 is not quite correct because !(counter==3) is not equivalent with it < 3. This is necessary to make the code work since findAll does not actually break the loop but continues until the end.
To emulate a real situation, let's say we have this code:
for (n in 0..5) {
if (n == 3)
break
println n
}
but we want to use each, so let's rewrite it using a function to simulate a break condition:
def breakWhen(nr) { nr == 3 }
(0..5)
.findAll { !breakWhen(it) }
.each { println it }
with the output:
0
1
2
4
5
now you see the problem with findAll. This does not stop, but ignores that element where the condition is not met.
To solve this issues, we need an extra variable to remember when the breaking condition become true. After this moment, findAll must ignore all remaining elements.
This is how it should look like:
def breakWhen(nr) { nr == 3 }
def loop = true
(0..5)
.findAll {
if (breakWhen(it))
loop = false
!breakWhen(it) && loop
} .each {
println it
}
with the output:
0
1
2
That's what we want!
(1..10).each{
if (it < 5)
println it
else
return false
You could break by RETURN. For example
def a = [1, 2, 3, 4, 5, 6, 7]
def ret = 0
a.each {def n ->
if (n > 5) {
ret = n
return ret
}
}
It works for me!

What is the best way in ruby to find if all the elements of one array are also present or not in the other array

I have following two arrays
a= [1,2,3,4]
b= [1,2]
c= [1,2,3,4,5]
I want a method which return boolean value something like following
a.<some_method>(b) #should return true
b.<some_method>(c) #should return false
suppose i use include? it will not work as it is expecting b as an element in the other array
currently i am doing something like following
b.all?{|x| a.include?(x) }
I want to know is there any better/fast way as my both the arrays having large lengths
Just check the result of second array subtracted from first array.
In your case B - A will be empty, but C - A will be non-empty...
In the simplest case the array operations are good.
But for extensive cases I think you need set operations. You can have a look at http://www.ruby-doc.org/stdlib-1.9.3/libdoc/set/rdoc/Set.html.
Like in your case, it should be
a= [1,2,3,4].to_set
b= [1,2].to_set
c= [1,2,3,4,5].to_set
a.superset?(b) # -> true
b.superset?(c) # -> false
array & other_array returns the matching elements between array and other array and removes any duplicates. You can create a boolean test to see if all elements of one array are in another by comparing the unique elements of the one array to the intersecting elements of the two combined arrays.
a = [1,2,3,4,5]
b = [2,3,4,5]
c = [4,5,6,7]
# check if all items in one array are in another array
def all_items_in_array?(original_array, test_array)
test_array.uniq == original_array & test_array
end
This method will return a boolean value
all_items_in_array?(a,b) # true
all_items_in_array?(a,c) # false
all_items_in_array?(b,c) # false
and for a boolean check with dupilcations
def all_items_including_duplicates_in_array?(original_array, test_array)
original_grouped = original_array.group_by{|item| item}.values
test_grouped = test_array.group_by{|item| item}.values
test_grouped == original_grouped & test_grouped
end
Both the array difference and Set#subset? answers are nice, but OP asked specifically about speed. The best way to answer performance questions is to actually time the different approaches. Benchmark to the rescue:
require 'benchmark'
require 'set'
BIG = 10_000
N = 1_000_000
SLOW_N = 500
a = [1,2,3,4]
b = [1,2]
c = [1,2,3,4,5]
bigA = (1..BIG).to_a
bigB = bigA.dup
bigB.pop
bigC = bigA.dup << (BIG+1)
setA = a.to_set
setB = b.to_set
setC = c.to_set
bigsetA = bigA.to_set
bigsetB = bigB.to_set
bigsetC = bigC.to_set
puts RUBY_DESCRIPTION
Benchmark.bm(21) do |x|
x.report('Array#-') { N.times{ (b-a).empty?; (c-a).empty? } }
x.report('Set#subset?') { N.times{ setB.subset?(setA); setC.subset?(setA) } }
x.report('big Array#-') { SLOW_N.times{ (bigB-bigA).empty?; (bigC-bigA).empty? } }
x.report('big Set#subset?') { SLOW_N.times{ bigsetB.subset?(bigsetA); bigsetC.subset?(bigsetA) } }
x.report('big all? Set#include?') { SLOW_N.times{ bigB.all?{|x| bigsetA.include?(x)}; bigC.all?{|x| bigsetA.include?(x)} } }
end
Results show that for small sets there's no significant difference. For large ones Set#subset? is about 20% faster:
ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-linux]
user system total real
Array#- 1.520000 0.000000 1.520000 ( 1.518501)
Set#subset? 1.520000 0.000000 1.520000 ( 1.533306)
big Array#- 2.180000 0.000000 2.180000 ( 2.180390)
big Set#subset? 1.720000 0.000000 1.720000 ( 1.724991)
big all? Set#include? 2.130000 0.000000 2.130000 ( 2.142015)
arr = [a, b, c]
arr.reduce(:&)
will get you the consistent elements
I am after the inconsistent ones as well.
You can also do this:
a = [1,2,3]
b = [2,4,6]
c = [2,3,4]
(a & b).any? or (a & b & c).any?

Resources